Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ coverage

# Python virtual environments (for running mkdocs locally)
venv
.venv

# Static documentation site generated by Mkdocs
site
Expand Down
35 changes: 35 additions & 0 deletions docs/snippets/idempotency/customizePersistenceLayer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { makeHandlerIdempotent } from '@aws-lambda-powertools/idempotency/middleware';
import { DynamoDBPersistenceLayer } from '@aws-lambda-powertools/idempotency/dynamodb';
import middy from '@middy/core';
import type { Context } from 'aws-lambda';
import type { Request, Response } from './types';

const persistenceStore = new DynamoDBPersistenceLayer({
tableName: 'idempotencyTableName',
keyAttr: 'idempotencyKey',
expiryAttr: 'expiresAt',
inProgressExpiryAttr: 'inProgressExpiresAt',
statusAttr: 'currentStatus',
dataAttr: 'resultData',
validationKeyAttr: 'validationKey',
});

export const handler = middy(
async (_event: Request, _context: Context): Promise<Response> => {
try {
// ... create payment

return {
paymentId: '1234567890',
message: 'success',
statusCode: 200,
};
} catch (error) {
throw new Error('Error creating payment');
}
}
).use(
makeHandlerIdempotent({
persistenceStore,
})
);
40 changes: 40 additions & 0 deletions docs/snippets/idempotency/makeHandlerIdempotent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { randomUUID } from 'node:crypto';
import { makeHandlerIdempotent } from '@aws-lambda-powertools/idempotency/middleware';
import { DynamoDBPersistenceLayer } from '@aws-lambda-powertools/idempotency/dynamodb';
import middy from '@middy/core';
import type { Context } from 'aws-lambda';
import type { Request, Response, SubscriptionResult } from './types';

const persistenceStore = new DynamoDBPersistenceLayer({
tableName: 'idempotencyTableName',
});

const createSubscriptionPayment = async (
event: Request
): Promise<SubscriptionResult> => {
// ... create payment
return {
id: randomUUID(),
productId: event.productId,
};
};

export const handler = middy(
async (event: Request, _context: Context): Promise<Response> => {
try {
const payment = await createSubscriptionPayment(event);

return {
paymentId: payment.id,
message: 'success',
statusCode: 200,
};
} catch (error) {
throw new Error('Error creating payment');
}
}
).use(
makeHandlerIdempotent({
persistenceStore,
})
);
59 changes: 59 additions & 0 deletions docs/snippets/idempotency/makeIdempotentAnyFunction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { randomUUID } from 'node:crypto';
import {
makeIdempotent,
IdempotencyConfig,
} from '@aws-lambda-powertools/idempotency';
import { DynamoDBPersistenceLayer } from '@aws-lambda-powertools/idempotency/dynamodb';
import type { Context } from 'aws-lambda';
import type { Request, Response, SubscriptionResult } from './types';

const persistenceStore = new DynamoDBPersistenceLayer({
tableName: 'idempotencyTableName',
});
const config = new IdempotencyConfig({});

const reportSubscriptionMetrics = async (
_transactionId: string,
_user: string
): Promise<void> => {
// ... send notification
};

const createSubscriptionPayment = makeIdempotent(
async (
transactionId: string,
event: Request
): Promise<SubscriptionResult> => {
// ... create payment
return {
id: transactionId,
productId: event.productId,
};
},
{
persistenceStore,
dataIndexArgument: 1,
config,
}
);

export const handler = async (
event: Request,
context: Context
): Promise<Response> => {
config.registerLambdaContext(context);
try {
const transactionId = randomUUID();
const payment = await createSubscriptionPayment(transactionId, event);

await reportSubscriptionMetrics(transactionId, event.user);

return {
paymentId: payment.id,
message: 'success',
statusCode: 200,
};
} catch (error) {
throw new Error('Error creating payment');
}
};
38 changes: 38 additions & 0 deletions docs/snippets/idempotency/makeIdempotentBase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { randomUUID } from 'node:crypto';
import { makeIdempotent } from '@aws-lambda-powertools/idempotency';
import { DynamoDBPersistenceLayer } from '@aws-lambda-powertools/idempotency/dynamodb';
import type { Context } from 'aws-lambda';
import type { Request, Response, SubscriptionResult } from './types';

const persistenceStore = new DynamoDBPersistenceLayer({
tableName: 'idempotencyTableName',
});

const createSubscriptionPayment = async (
event: Request
): Promise<SubscriptionResult> => {
// ... create payment
return {
id: randomUUID(),
productId: event.productId,
};
};

export const handler = makeIdempotent(
async (event: Request, _context: Context): Promise<Response> => {
try {
const payment = await createSubscriptionPayment(event);

return {
paymentId: payment.id,
message: 'success',
statusCode: 200,
};
} catch (error) {
throw new Error('Error creating payment');
}
},
{
persistenceStore,
}
);
51 changes: 51 additions & 0 deletions docs/snippets/idempotency/makeIdempotentJmes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { randomUUID } from 'node:crypto';
import {
makeIdempotent,
IdempotencyConfig,
} from '@aws-lambda-powertools/idempotency';
import { DynamoDBPersistenceLayer } from '@aws-lambda-powertools/idempotency/dynamodb';
import type { Context } from 'aws-lambda';
import type { Request, Response, SubscriptionResult } from './types';

const persistenceStore = new DynamoDBPersistenceLayer({
tableName: 'idempotencyTableName',
});

const createSubscriptionPayment = async (
user: string,
productId: string
): Promise<SubscriptionResult> => {
// ... create payment
return {
id: randomUUID(),
productId: productId,
};
};

// Extract the idempotency key from the request headers
const config = new IdempotencyConfig({
eventKeyJmesPath: 'headers."X-Idempotency-Key"',
});

export const handler = makeIdempotent(
async (event: Request, _context: Context): Promise<Response> => {
try {
const payment = await createSubscriptionPayment(
event.user,
event.productId
);

return {
paymentId: payment.id,
message: 'success',
statusCode: 200,
};
} catch (error) {
throw new Error('Error creating payment');
}
},
{
persistenceStore,
config,
}
);
51 changes: 51 additions & 0 deletions docs/snippets/idempotency/makeIdempotentLambdaContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { randomUUID } from 'node:crypto';
import {
makeIdempotent,
IdempotencyConfig,
} from '@aws-lambda-powertools/idempotency';
import { DynamoDBPersistenceLayer } from '@aws-lambda-powertools/idempotency/dynamodb';
import type { Context } from 'aws-lambda';
import type { Request, Response, SubscriptionResult } from './types';

const persistenceStore = new DynamoDBPersistenceLayer({
tableName: 'idempotencyTableName',
});
const config = new IdempotencyConfig({});

const createSubscriptionPayment = makeIdempotent(
async (
transactionId: string,
event: Request
): Promise<SubscriptionResult> => {
// ... create payment
return {
id: transactionId,
productId: event.productId,
};
},
{
persistenceStore,
dataIndexArgument: 1,
config,
}
);

export const handler = async (
event: Request,
context: Context
): Promise<Response> => {
// Register the Lambda context to the IdempotencyConfig instance
config.registerLambdaContext(context);
try {
const transactionId = randomUUID();
const payment = await createSubscriptionPayment(transactionId, event);

return {
paymentId: payment.id,
message: 'success',
statusCode: 200,
};
} catch (error) {
throw new Error('Error creating payment');
}
};
20 changes: 20 additions & 0 deletions docs/snippets/idempotency/requiredIdempotencyKey.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import {
IdempotencyConfig,
makeIdempotent,
} from '@aws-lambda-powertools/idempotency';
import { DynamoDBPersistenceLayer } from '@aws-lambda-powertools/idempotency/dynamodb';

const persistenceStore = new DynamoDBPersistenceLayer({
tableName: 'IdempotencyTable',
});

// Requires "user"."uid" and "orderId" to be present
const config = new IdempotencyConfig({
eventKeyJmesPath: '[user.uid, orderId]',
throwOnNoIdempotencyKey: true,
});

export const handler = makeIdempotent((_event: unknown) => ({}), {
persistenceStore,
config,
});
15 changes: 15 additions & 0 deletions docs/snippets/idempotency/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
type Request = {
user: string;
productId: string;
};

type Response = {
[key: string]: unknown;
};

type SubscriptionResult = {
id: string;
productId: string;
};

export { Request, Response, SubscriptionResult };
30 changes: 30 additions & 0 deletions docs/snippets/idempotency/workingWithCompositeKey.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { makeHandlerIdempotent } from '@aws-lambda-powertools/idempotency/middleware';
import { DynamoDBPersistenceLayer } from '@aws-lambda-powertools/idempotency/dynamodb';
import middy from '@middy/core';
import type { Context } from 'aws-lambda';
import type { Request, Response } from './types';

const persistenceStore = new DynamoDBPersistenceLayer({
tableName: 'idempotencyTableName',
sortKeyAttr: 'sort_key',
});

export const handler = middy(
async (_event: Request, _context: Context): Promise<Response> => {
try {
// ... create payment

return {
paymentId: '12345',
message: 'success',
statusCode: 200,
};
} catch (error) {
throw new Error('Error creating payment');
}
}
).use(
makeHandlerIdempotent({
persistenceStore,
})
);
32 changes: 32 additions & 0 deletions docs/snippets/idempotency/workingWithCustomClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { makeIdempotent } from '@aws-lambda-powertools/idempotency';
import { DynamoDBPersistenceLayer } from '@aws-lambda-powertools/idempotency/dynamodb';
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import type { Context } from 'aws-lambda';
import type { Request, Response } from './types';

const customDynamoDBClient = new DynamoDBClient({
endpoint: 'http://localhost:8000',
});
const persistenceStore = new DynamoDBPersistenceLayer({
tableName: 'idempotencyTableName',
awsSdkV3Client: customDynamoDBClient,
});

export const handler = makeIdempotent(
async (_event: Request, _context: Context): Promise<Response> => {
try {
// ... create payment

return {
paymentId: '12345',
message: 'success',
statusCode: 200,
};
} catch (error) {
throw new Error('Error creating payment');
}
},
{
persistenceStore,
}
);
Loading