feat: Upgrade to asynchronous event bus with retry queue and backoff strategy (#290)

## Description
<!-- Briefly describe the purpose and scope of your changes -->


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Introduced a retry and dead-letter queue system for more robust event
processing.
- Added a retry handler for processing failed Lambda invocations with
exponential backoff.
- Enhanced event handling to support retry logic and improved error
management.

- **Refactor**
- Replaced SQS-based library event processing with an event bus-based
approach.
- Updated event names and structure for improved clarity and
consistency.
  - Removed legacy library queue and related infrastructure.

- **Chores**
  - Updated dependencies to include the AWS Lambda client.
  - Cleaned up unused code and removed deprecated event handling logic.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Wanjohi
2025-06-04 07:53:30 +03:00
committed by GitHub
parent 8f4bb05143
commit e67a8d2b32
11 changed files with 494 additions and 308 deletions

View File

@@ -4,7 +4,6 @@ import { domain } from "./dns";
import { secret } from "./secret";
import { cluster } from "./cluster";
import { postgres } from "./postgres";
import { libraryQueue } from "./steam";
export const apiService = new sst.aws.Service("Api", {
cluster,
@@ -14,7 +13,6 @@ export const apiService = new sst.aws.Service("Api", {
bus,
auth,
postgres,
libraryQueue,
secret.SteamApiKey,
secret.PolarSecret,
secret.PolarWebhookSecret,

View File

@@ -1,12 +1,15 @@
import { vpc } from "./vpc";
import { secret } from "./secret";
// import { email } from "./email";
import { storage } from "./storage";
import { postgres } from "./postgres";
export const dlq = new sst.aws.Queue("Dlq");
export const retryQueue = new sst.aws.Queue("RetryQueue");
export const bus = new sst.aws.Bus("Bus");
bus.subscribe("Event", {
export const eventSub = bus.subscribe("Event", {
vpc,
handler: "packages/functions/src/events/index.handler",
link: [
@@ -14,22 +17,54 @@ bus.subscribe("Event", {
bus,
storage,
postgres,
retryQueue,
secret.PolarSecret,
secret.SteamApiKey
],
timeout: "10 minutes",
environment: {
RETRIES: "2",
},
memory: "3002 MB",// For faster processing of large(r) images
timeout: "10 minutes",
});
new aws.lambda.FunctionEventInvokeConfig("EventConfig", {
functionName: $resolve([eventSub.nodes.function.name]).apply(
([name]) => name,
),
maximumRetryAttempts: 1,
destinationConfig: {
onFailure: {
destination: retryQueue.arn,
},
},
});
retryQueue.subscribe({
vpc,
handler: "packages/functions/src/queues/retry.handler",
timeout: "30 seconds",
environment: {
RETRIER_QUEUE_URL: retryQueue.url,
},
link: [
dlq,
retryQueue,
eventSub.nodes.function,
],
permissions: [
{
actions: ["ses:SendEmail","sqs:SendMessage"],
resources: ["*"],
actions: ["lambda:GetFunction", "lambda:InvokeFunction"],
resources: [
$interpolate`arn:aws:lambda:${aws.getRegionOutput().name}:${aws.getCallerIdentityOutput().accountId}:function:*`,
],
},
],
// transform: {
// function: {
// deadLetterConfig: {
// targetArn: EventDlq.arn,
// },
// },
// },
transform: {
function: {
deadLetterConfig: {
targetArn: dlq.arn,
},
},
},
});

View File

@@ -1,29 +0,0 @@
import { bus } from "./bus";
import { vpc } from "./vpc";
import { secret } from "./secret";
import { postgres } from "./postgres";
export const libraryDlq = new sst.aws.Queue("LibraryDLQ");
export const libraryQueue = new sst.aws.Queue("LibraryQueue", {
dlq: libraryDlq.arn,
visibilityTimeout: "5 minutes",
});
libraryQueue.subscribe({
vpc,
memory: "3002 MB",
timeout: "5 minutes",
handler: "packages/functions/src/queues/library.handler",
link: [
bus,
postgres,
secret.SteamApiKey
],
permissions: [
{
actions: ["sqs:SendMessage"],
resources: ["*"],
},
],
});