@lafken/queue 0.6.4 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +176 -58
- package/lib/main/event/event.d.ts +92 -0
- package/lib/main/event/event.js +92 -0
- package/lib/main/queue/queue.d.ts +59 -0
- package/lib/main/queue/queue.js +59 -0
- package/lib/resolver/queue/queue.d.ts +1 -1
- package/lib/resolver/queue/queue.js +2 -2
- package/package.json +40 -19
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @lafken/queue
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Define and consume Amazon SQS queues using TypeScript decorators. `@lafken/queue` lets you declare Standard and FIFO queues, map message data to typed handler parameters, and send messages at runtime through a built-in service client.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -8,122 +8,240 @@
|
|
|
8
8
|
npm install @lafken/queue
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Getting Started
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Define a queue class with `@Queue`, add consumer methods with `@Standard` or `@Fifo`, and register everything through `QueueResolver`:
|
|
14
14
|
|
|
15
15
|
```typescript
|
|
16
|
+
import { createApp, createModule } from '@lafken/main';
|
|
16
17
|
import { QueueResolver } from '@lafken/queue/resolver';
|
|
18
|
+
import { Queue, Standard, Payload, Param, Event } from '@lafken/queue/main';
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
// ...
|
|
24
|
-
});
|
|
20
|
+
// 1. Define the message payload
|
|
21
|
+
@Payload()
|
|
22
|
+
export class OrderMessage {
|
|
23
|
+
@Param({ source: 'body', parse: true })
|
|
24
|
+
orderId: string;
|
|
25
25
|
|
|
26
|
+
@Param({ source: 'body', parse: true })
|
|
27
|
+
total: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 2. Define the queue and its consumer
|
|
26
31
|
@Queue()
|
|
27
|
-
class
|
|
28
|
-
|
|
32
|
+
export class OrderQueue {
|
|
33
|
+
@Standard({ batchSize: 5, visibilityTimeout: 60 })
|
|
34
|
+
processOrder(@Event(OrderMessage) message: OrderMessage) {
|
|
35
|
+
console.log(`Processing order ${message.orderId}`);
|
|
36
|
+
}
|
|
29
37
|
}
|
|
30
38
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
39
|
+
// 3. Register in a module
|
|
40
|
+
const orderModule = createModule({
|
|
41
|
+
name: 'order',
|
|
42
|
+
resources: [OrderQueue],
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// 4. Add the resolver to the app
|
|
46
|
+
createApp({
|
|
47
|
+
name: 'my-app',
|
|
48
|
+
resolvers: [new QueueResolver()],
|
|
49
|
+
modules: [orderModule],
|
|
36
50
|
});
|
|
37
51
|
```
|
|
38
52
|
|
|
53
|
+
Each `@Standard` or `@Fifo` method becomes an independent Lambda function with its own SQS queue and event source mapping.
|
|
54
|
+
|
|
39
55
|
## Features
|
|
40
56
|
|
|
41
|
-
###
|
|
57
|
+
### Queue Class
|
|
42
58
|
|
|
43
|
-
Use the `@Queue` decorator to
|
|
59
|
+
Use the `@Queue` decorator to group related queue consumers in a single class. A queue class can contain multiple `@Standard` and `@Fifo` handlers:
|
|
44
60
|
|
|
45
61
|
```typescript
|
|
46
|
-
import { Queue, Standard, Fifo } from '@lafken/queue';
|
|
62
|
+
import { Queue, Standard, Fifo } from '@lafken/queue/main';
|
|
47
63
|
|
|
48
64
|
@Queue()
|
|
49
|
-
export class
|
|
50
|
-
|
|
65
|
+
export class NotificationQueue {
|
|
66
|
+
@Standard({ queueName: 'email-notifications' })
|
|
67
|
+
sendEmail() { }
|
|
68
|
+
|
|
69
|
+
@Fifo({ queueName: 'sms-notifications', contentBasedDeduplication: true })
|
|
70
|
+
sendSms() { }
|
|
51
71
|
}
|
|
52
72
|
```
|
|
53
73
|
|
|
54
74
|
### Standard Queues
|
|
55
75
|
|
|
56
|
-
Use the `@Standard` decorator to
|
|
76
|
+
Use the `@Standard` decorator to create a standard (non-FIFO) SQS queue consumer. Messages are delivered at least once with best-effort ordering:
|
|
57
77
|
|
|
58
78
|
```typescript
|
|
59
79
|
@Standard({
|
|
60
|
-
queueName: '
|
|
61
|
-
visibilityTimeout: 30,
|
|
80
|
+
queueName: 'reports',
|
|
62
81
|
batchSize: 10,
|
|
82
|
+
visibilityTimeout: 120,
|
|
83
|
+
maxConcurrency: 5,
|
|
63
84
|
})
|
|
64
|
-
|
|
65
|
-
// Process messages
|
|
85
|
+
generateReport(@Event(ReportMessage) message: ReportMessage) {
|
|
86
|
+
// Process up to 10 messages per invocation
|
|
66
87
|
}
|
|
67
88
|
```
|
|
68
89
|
|
|
90
|
+
If `queueName` is omitted, the method name is used as the queue name.
|
|
91
|
+
|
|
92
|
+
#### Standard Queue Options
|
|
93
|
+
|
|
94
|
+
| Option | Type | Description |
|
|
95
|
+
| --------------------- | -------- | ------------------------------------------------------------------ |
|
|
96
|
+
| `queueName` | `string` | Queue name (defaults to the method name) |
|
|
97
|
+
| `batchSize` | `1–10` | Number of messages per Lambda invocation |
|
|
98
|
+
| `visibilityTimeout` | `number` | Seconds a message is hidden from other consumers while processing |
|
|
99
|
+
| `deliveryDelay` | `number` | Seconds to delay message delivery after it is sent |
|
|
100
|
+
| `retentionPeriod` | `number` | Seconds messages are retained before automatic deletion |
|
|
101
|
+
| `maxMessageSizeBytes` | `number` | Maximum message size in bytes |
|
|
102
|
+
| `maxConcurrency` | `number` | Maximum concurrent Lambda invocations for this queue |
|
|
103
|
+
| `maxBatchingWindow` | `number` | Seconds to wait gathering messages into a batch before invoking |
|
|
104
|
+
| `lambda` | `object` | Lambda-specific configuration (memory, timeout, etc.) |
|
|
105
|
+
|
|
69
106
|
### FIFO Queues
|
|
70
107
|
|
|
71
|
-
Use the `@Fifo` decorator for FIFO (First-In-First-Out) queues.
|
|
108
|
+
Use the `@Fifo` decorator for FIFO (First-In-First-Out) queues. FIFO queues guarantee exactly-once processing and strict message ordering. The queue name automatically gets a `.fifo` suffix:
|
|
72
109
|
|
|
73
110
|
```typescript
|
|
74
111
|
@Fifo({
|
|
75
|
-
queueName: '
|
|
112
|
+
queueName: 'payment-processing',
|
|
76
113
|
contentBasedDeduplication: true,
|
|
114
|
+
batchSize: 1,
|
|
77
115
|
})
|
|
78
|
-
|
|
79
|
-
//
|
|
116
|
+
processPayment(@Event(PaymentMessage) message: PaymentMessage) {
|
|
117
|
+
// Messages are processed in exact send order
|
|
80
118
|
}
|
|
81
119
|
```
|
|
82
120
|
|
|
83
|
-
|
|
121
|
+
FIFO queues support all standard queue options plus:
|
|
122
|
+
|
|
123
|
+
| Option | Type | Description |
|
|
124
|
+
| --------------------------- | --------- | --------------------------------------------------------------- |
|
|
125
|
+
| `contentBasedDeduplication` | `boolean` | Use message content to generate deduplication IDs automatically |
|
|
84
126
|
|
|
85
|
-
|
|
127
|
+
> [!NOTE]
|
|
128
|
+
> FIFO queues automatically enable `ReportBatchItemFailures`, allowing partial batch failure reporting.
|
|
86
129
|
|
|
87
|
-
|
|
130
|
+
### Message Payload
|
|
88
131
|
|
|
89
|
-
|
|
132
|
+
Use `@Payload` on a class to define the structure of SQS messages. Decorate each property with `@Param` to specify where the value is extracted from in the SQS record:
|
|
90
133
|
|
|
91
134
|
```typescript
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
)
|
|
97
|
-
|
|
135
|
+
import { Payload, Param } from '@lafken/queue/main';
|
|
136
|
+
|
|
137
|
+
@Payload()
|
|
138
|
+
export class TaskMessage {
|
|
139
|
+
@Param({ source: 'attribute', type: String })
|
|
140
|
+
correlationId: string;
|
|
141
|
+
|
|
142
|
+
@Param({ source: 'body', parse: true })
|
|
143
|
+
taskName: string;
|
|
144
|
+
|
|
145
|
+
@Param({ source: 'body', parse: true })
|
|
146
|
+
priority: number;
|
|
98
147
|
}
|
|
99
148
|
```
|
|
100
149
|
|
|
101
|
-
####
|
|
150
|
+
#### @Param Options
|
|
102
151
|
|
|
103
|
-
|
|
152
|
+
| Option | Type | Default | Description |
|
|
153
|
+
| -------- | ------------------------- | ------------- | ------------------------------------------------ |
|
|
154
|
+
| `source` | `'attribute' \| 'body'` | `'attribute'` | Where to extract the value from the SQS record |
|
|
155
|
+
| `parse` | `boolean` | `false` | JSON-parse the message body before extraction |
|
|
156
|
+
| `type` | `String \| Number \| ...` | inferred | Data type of the extracted value |
|
|
157
|
+
| `name` | `string` | property name | Override the field name used for extraction |
|
|
158
|
+
|
|
159
|
+
- **`source: 'attribute'`** — reads from SQS message attributes (supports `String` and `Number` types)
|
|
160
|
+
- **`source: 'body'`** — reads from the message body. Set `parse: true` to JSON-parse the body and extract a specific field
|
|
161
|
+
|
|
162
|
+
> [!NOTE]
|
|
163
|
+
> Only one `@Param` with `source: 'body'` and `parse: false` (raw body) is allowed per handler.
|
|
164
|
+
|
|
165
|
+
#### @Field Decorator
|
|
166
|
+
|
|
167
|
+
Use `@Field` to include a property in the payload schema without specifying an extraction source:
|
|
104
168
|
|
|
105
169
|
```typescript
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
)
|
|
111
|
-
|
|
170
|
+
import { Payload, Field } from '@lafken/queue/main';
|
|
171
|
+
|
|
172
|
+
@Payload()
|
|
173
|
+
export class SimpleMessage {
|
|
174
|
+
@Field()
|
|
175
|
+
action: string;
|
|
176
|
+
|
|
177
|
+
@Field()
|
|
178
|
+
timestamp: number;
|
|
112
179
|
}
|
|
113
180
|
```
|
|
114
181
|
|
|
115
|
-
|
|
182
|
+
### Consuming Messages
|
|
116
183
|
|
|
117
|
-
|
|
184
|
+
Bind a typed payload to a handler method using the `@Event` parameter decorator. Pass the payload class so the framework can automatically extract and map fields from the SQS record at runtime:
|
|
118
185
|
|
|
119
186
|
```typescript
|
|
120
|
-
|
|
121
|
-
userId: string;
|
|
122
|
-
email: string;
|
|
123
|
-
}
|
|
187
|
+
import { Queue, Standard, Event } from '@lafken/queue/main';
|
|
124
188
|
|
|
125
|
-
@
|
|
126
|
-
|
|
127
|
-
|
|
189
|
+
@Queue()
|
|
190
|
+
export class AlertQueue {
|
|
191
|
+
@Standard({ queueName: 'alerts', batchSize: 5 })
|
|
192
|
+
processAlert(@Event(AlertMessage) alert: AlertMessage) {
|
|
193
|
+
console.log(`Alert from ${alert.source}: ${alert.message}`);
|
|
194
|
+
}
|
|
128
195
|
}
|
|
129
196
|
```
|
|
197
|
+
|
|
198
|
+
### Sending Messages
|
|
199
|
+
|
|
200
|
+
Use `QueueService` at runtime to send messages to any SQS queue:
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
import { QueueService } from '@lafken/queue/service';
|
|
204
|
+
|
|
205
|
+
// Send a single message
|
|
206
|
+
await QueueService.sendMessage({
|
|
207
|
+
url: 'https://sqs.us-east-1.amazonaws.com/123456789/orders',
|
|
208
|
+
body: { orderId: 'ord-123', total: 49.99 },
|
|
209
|
+
delay: 10,
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
// Send to a FIFO queue
|
|
213
|
+
await QueueService.sendMessage({
|
|
214
|
+
url: 'https://sqs.us-east-1.amazonaws.com/123456789/payments.fifo',
|
|
215
|
+
body: { paymentId: 'pay-456', amount: 100 },
|
|
216
|
+
groupId: 'customer-789',
|
|
217
|
+
deduplicationId: 'pay-456',
|
|
218
|
+
});
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
#### SendMessage Options
|
|
222
|
+
|
|
223
|
+
| Option | Type | Description |
|
|
224
|
+
| ------------------- | ---------------------------------- | -------------------------------------------------- |
|
|
225
|
+
| `url` | `string` | Full SQS queue URL |
|
|
226
|
+
| `body` | `any` | Message body (automatically JSON-stringified) |
|
|
227
|
+
| `attributes` | `Record<string, string \| number>` | SQS message attributes |
|
|
228
|
+
| `delay` | `number` | Delay in seconds before the message becomes visible |
|
|
229
|
+
| `groupId` | `string` | Message group ID (FIFO queues only) |
|
|
230
|
+
| `deduplicationId` | `string` | Deduplication ID (FIFO queues only) |
|
|
231
|
+
|
|
232
|
+
### Sending Batch Messages
|
|
233
|
+
|
|
234
|
+
Send multiple messages in a single API call:
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
import { QueueService } from '@lafken/queue/service';
|
|
238
|
+
|
|
239
|
+
await QueueService.sendBatchMessage({
|
|
240
|
+
url: 'https://sqs.us-east-1.amazonaws.com/123456789/tasks',
|
|
241
|
+
messages: [
|
|
242
|
+
{ body: { task: 'resize-image', fileId: 'f1' } },
|
|
243
|
+
{ body: { task: 'resize-image', fileId: 'f2' }, delay: 30 },
|
|
244
|
+
{ body: { task: 'generate-thumbnail', fileId: 'f3' } },
|
|
245
|
+
],
|
|
246
|
+
});
|
|
247
|
+
```
|
|
@@ -1,7 +1,99 @@
|
|
|
1
1
|
import type { ParamProps } from './event.types';
|
|
2
2
|
export declare const queueFieldKey: string;
|
|
3
3
|
export declare const queuePayloadKey: string;
|
|
4
|
+
/**
|
|
5
|
+
* Class decorator that declares a class as an SQS message payload.
|
|
6
|
+
*
|
|
7
|
+
* The decorated class defines the structure of data carried in a queue
|
|
8
|
+
* message. Use `@Param` or `@Field` on its properties to describe
|
|
9
|
+
* where each value is extracted from in the SQS record (message
|
|
10
|
+
* attributes or body).
|
|
11
|
+
*
|
|
12
|
+
* Works both at build time and at Lambda invocation time, so the
|
|
13
|
+
* same class can be used for sending and receiving messages.
|
|
14
|
+
*
|
|
15
|
+
* @param props - Optional payload configuration (e.g. a custom `name`).
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* @Payload()
|
|
20
|
+
* export class OrderMessage {
|
|
21
|
+
* @Param({ source: 'attribute' })
|
|
22
|
+
* orderId: string;
|
|
23
|
+
*
|
|
24
|
+
* @Param({ source: 'body', parse: true })
|
|
25
|
+
* details: OrderDetails;
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
4
29
|
export declare const Payload: (props?: import("@lafken/common").PayloadProps | undefined) => (target: Function) => void;
|
|
30
|
+
/**
|
|
31
|
+
* Property decorator that maps a class field to a value extracted
|
|
32
|
+
* from an SQS message.
|
|
33
|
+
*
|
|
34
|
+
* By default the value is read from a **message attribute** whose name
|
|
35
|
+
* matches the property. Set `source: 'body'` to extract it from the
|
|
36
|
+
* message body instead, and optionally enable `parse: true` to
|
|
37
|
+
* JSON-parse the body before extraction.
|
|
38
|
+
*
|
|
39
|
+
* @param props - Optional extraction configuration (source, type, parse).
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* @Payload()
|
|
44
|
+
* export class NotificationMessage {
|
|
45
|
+
* @Param({ source: 'attribute', type: String })
|
|
46
|
+
* userId: string;
|
|
47
|
+
*
|
|
48
|
+
* @Param({ source: 'body', parse: true })
|
|
49
|
+
* content: NotificationContent;
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
5
53
|
export declare const Param: (props?: ParamProps | undefined) => (target: any, destinationName: string) => void;
|
|
54
|
+
/**
|
|
55
|
+
* Property decorator that registers a class field as a generic
|
|
56
|
+
* queue message field.
|
|
57
|
+
*
|
|
58
|
+
* Unlike `@Param`, this decorator does not configure a specific
|
|
59
|
+
* extraction source or parsing behaviour — it simply marks the
|
|
60
|
+
* property for inclusion in the message payload schema.
|
|
61
|
+
*
|
|
62
|
+
* @param props - Optional field configuration (e.g. a custom `name` or `type`).
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* @Payload()
|
|
67
|
+
* export class SimpleMessage {
|
|
68
|
+
* @Field()
|
|
69
|
+
* action: string;
|
|
70
|
+
*
|
|
71
|
+
* @Field()
|
|
72
|
+
* timestamp: number;
|
|
73
|
+
* }
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
6
76
|
export declare const Field: (props?: import("@lafken/common").FieldProps | undefined) => (target: any, destinationName: string) => void;
|
|
77
|
+
/**
|
|
78
|
+
* Parameter decorator that binds the incoming SQS event to a typed
|
|
79
|
+
* payload class on a handler method argument.
|
|
80
|
+
*
|
|
81
|
+
* Pass a class decorated with `@Payload` so the framework can
|
|
82
|
+
* automatically extract and map each field from the raw SQS record
|
|
83
|
+
* into a strongly-typed object at runtime.
|
|
84
|
+
*
|
|
85
|
+
* @param eventField - The payload class describing the expected
|
|
86
|
+
* message structure.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```ts
|
|
90
|
+
* @Queue()
|
|
91
|
+
* export class OrderQueue {
|
|
92
|
+
* @Consumer()
|
|
93
|
+
* process(@Event(OrderMessage) msg: OrderMessage) {
|
|
94
|
+
* // msg fields are extracted from the SQS record
|
|
95
|
+
* }
|
|
96
|
+
* }
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
7
99
|
export declare const Event: (eventField: Function) => (target: any, methodName: string, _number: number) => void;
|
package/lib/main/event/event.js
CHANGED
|
@@ -5,11 +5,59 @@ const common_1 = require("@lafken/common");
|
|
|
5
5
|
const queue_1 = require("../queue");
|
|
6
6
|
exports.queueFieldKey = (0, common_1.createFieldName)(queue_1.RESOURCE_TYPE, common_1.FieldProperties.field);
|
|
7
7
|
exports.queuePayloadKey = (0, common_1.createFieldName)(queue_1.RESOURCE_TYPE, common_1.FieldProperties.payload);
|
|
8
|
+
/**
|
|
9
|
+
* Class decorator that declares a class as an SQS message payload.
|
|
10
|
+
*
|
|
11
|
+
* The decorated class defines the structure of data carried in a queue
|
|
12
|
+
* message. Use `@Param` or `@Field` on its properties to describe
|
|
13
|
+
* where each value is extracted from in the SQS record (message
|
|
14
|
+
* attributes or body).
|
|
15
|
+
*
|
|
16
|
+
* Works both at build time and at Lambda invocation time, so the
|
|
17
|
+
* same class can be used for sending and receiving messages.
|
|
18
|
+
*
|
|
19
|
+
* @param props - Optional payload configuration (e.g. a custom `name`).
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* @Payload()
|
|
24
|
+
* export class OrderMessage {
|
|
25
|
+
* @Param({ source: 'attribute' })
|
|
26
|
+
* orderId: string;
|
|
27
|
+
*
|
|
28
|
+
* @Param({ source: 'body', parse: true })
|
|
29
|
+
* details: OrderDetails;
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
8
33
|
exports.Payload = (0, common_1.createPayloadDecorator)({
|
|
9
34
|
prefix: queue_1.RESOURCE_TYPE,
|
|
10
35
|
createUniqueId: false,
|
|
11
36
|
enableInLambdaInvocation: true,
|
|
12
37
|
});
|
|
38
|
+
/**
|
|
39
|
+
* Property decorator that maps a class field to a value extracted
|
|
40
|
+
* from an SQS message.
|
|
41
|
+
*
|
|
42
|
+
* By default the value is read from a **message attribute** whose name
|
|
43
|
+
* matches the property. Set `source: 'body'` to extract it from the
|
|
44
|
+
* message body instead, and optionally enable `parse: true` to
|
|
45
|
+
* JSON-parse the body before extraction.
|
|
46
|
+
*
|
|
47
|
+
* @param props - Optional extraction configuration (source, type, parse).
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* @Payload()
|
|
52
|
+
* export class NotificationMessage {
|
|
53
|
+
* @Param({ source: 'attribute', type: String })
|
|
54
|
+
* userId: string;
|
|
55
|
+
*
|
|
56
|
+
* @Param({ source: 'body', parse: true })
|
|
57
|
+
* content: NotificationContent;
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
13
61
|
exports.Param = (0, common_1.createFieldDecorator)({
|
|
14
62
|
prefix: queue_1.RESOURCE_TYPE,
|
|
15
63
|
enableInLambdaInvocation: true,
|
|
@@ -21,11 +69,55 @@ exports.Param = (0, common_1.createFieldDecorator)({
|
|
|
21
69
|
};
|
|
22
70
|
},
|
|
23
71
|
});
|
|
72
|
+
/**
|
|
73
|
+
* Property decorator that registers a class field as a generic
|
|
74
|
+
* queue message field.
|
|
75
|
+
*
|
|
76
|
+
* Unlike `@Param`, this decorator does not configure a specific
|
|
77
|
+
* extraction source or parsing behaviour — it simply marks the
|
|
78
|
+
* property for inclusion in the message payload schema.
|
|
79
|
+
*
|
|
80
|
+
* @param props - Optional field configuration (e.g. a custom `name` or `type`).
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* @Payload()
|
|
85
|
+
* export class SimpleMessage {
|
|
86
|
+
* @Field()
|
|
87
|
+
* action: string;
|
|
88
|
+
*
|
|
89
|
+
* @Field()
|
|
90
|
+
* timestamp: number;
|
|
91
|
+
* }
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
24
94
|
exports.Field = (0, common_1.createFieldDecorator)({
|
|
25
95
|
prefix: queue_1.RESOURCE_TYPE,
|
|
26
96
|
enableInLambdaInvocation: true,
|
|
27
97
|
getMetadata: () => ({}),
|
|
28
98
|
});
|
|
99
|
+
/**
|
|
100
|
+
* Parameter decorator that binds the incoming SQS event to a typed
|
|
101
|
+
* payload class on a handler method argument.
|
|
102
|
+
*
|
|
103
|
+
* Pass a class decorated with `@Payload` so the framework can
|
|
104
|
+
* automatically extract and map each field from the raw SQS record
|
|
105
|
+
* into a strongly-typed object at runtime.
|
|
106
|
+
*
|
|
107
|
+
* @param eventField - The payload class describing the expected
|
|
108
|
+
* message structure.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```ts
|
|
112
|
+
* @Queue()
|
|
113
|
+
* export class OrderQueue {
|
|
114
|
+
* @Consumer()
|
|
115
|
+
* process(@Event(OrderMessage) msg: OrderMessage) {
|
|
116
|
+
* // msg fields are extracted from the SQS record
|
|
117
|
+
* }
|
|
118
|
+
* }
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
29
121
|
const Event = (eventField) => (0, common_1.createEventDecorator)({
|
|
30
122
|
prefix: queue_1.RESOURCE_TYPE,
|
|
31
123
|
enableInLambdaInvocation: true,
|
|
@@ -1,6 +1,65 @@
|
|
|
1
1
|
import 'reflect-metadata';
|
|
2
2
|
import type { FifoProps, StandardProps } from './queue.types';
|
|
3
3
|
export declare const RESOURCE_TYPE: "QUEUE";
|
|
4
|
+
/**
|
|
5
|
+
* Class decorator that registers a class as an SQS queue resource.
|
|
6
|
+
*
|
|
7
|
+
* The decorated class groups one or more consumer handlers (`@Standard`
|
|
8
|
+
* or `@Fifo`) that process messages from SQS queues.
|
|
9
|
+
*
|
|
10
|
+
* @param props - Optional resource configuration (e.g. a custom `name`).
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* @Queue()
|
|
15
|
+
* export class NotificationQueue {
|
|
16
|
+
* @Standard({ batchSize: 5 })
|
|
17
|
+
* process(@Event(NotificationMessage) msg: NotificationMessage) { }
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
4
21
|
export declare const Queue: (props?: import("@lafken/common").ResourceProps | undefined) => (constructor: Function) => void;
|
|
22
|
+
/**
|
|
23
|
+
* Method decorator that registers a handler as a **standard** SQS queue
|
|
24
|
+
* consumer.
|
|
25
|
+
*
|
|
26
|
+
* The decorated method becomes a Lambda function triggered by messages
|
|
27
|
+
* from a standard (non-FIFO) SQS queue. Configure delivery delay,
|
|
28
|
+
* batch size, visibility timeout, and other queue settings through
|
|
29
|
+
* the decorator props.
|
|
30
|
+
*
|
|
31
|
+
* @param props - Standard queue configuration (deliveryDelay, batchSize,
|
|
32
|
+
* visibilityTimeout, retentionPeriod, lambda, etc.).
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* @Queue()
|
|
37
|
+
* export class EmailQueue {
|
|
38
|
+
* @Standard({ batchSize: 10, visibilityTimeout: 60 })
|
|
39
|
+
* send(@Event(EmailPayload) msg: EmailPayload) { }
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
5
43
|
export declare const Standard: (props?: StandardProps | undefined) => (target: any, methodName: string, descriptor: PropertyDescriptor) => any;
|
|
44
|
+
/**
|
|
45
|
+
* Method decorator that registers a handler as a **FIFO** SQS queue
|
|
46
|
+
* consumer.
|
|
47
|
+
*
|
|
48
|
+
* The decorated method becomes a Lambda function triggered by messages
|
|
49
|
+
* from a FIFO queue, which guarantees exactly-once processing and
|
|
50
|
+
* strict ordering. In addition to all standard queue options, FIFO
|
|
51
|
+
* queues support `contentBasedDeduplication`.
|
|
52
|
+
*
|
|
53
|
+
* @param props - FIFO queue configuration (contentBasedDeduplication,
|
|
54
|
+
* batchSize, visibilityTimeout, lambda, etc.).
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```ts
|
|
58
|
+
* @Queue()
|
|
59
|
+
* export class PaymentQueue {
|
|
60
|
+
* @Fifo({ contentBasedDeduplication: true, batchSize: 1 })
|
|
61
|
+
* process(@Event(PaymentMessage) msg: PaymentMessage) { }
|
|
62
|
+
* }
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
6
65
|
export declare const Fifo: (props?: FifoProps | undefined) => (target: any, methodName: string, descriptor: PropertyDescriptor) => any;
|
package/lib/main/queue/queue.js
CHANGED
|
@@ -4,6 +4,23 @@ exports.Fifo = exports.Standard = exports.Queue = exports.RESOURCE_TYPE = void 0
|
|
|
4
4
|
require("reflect-metadata");
|
|
5
5
|
const common_1 = require("@lafken/common");
|
|
6
6
|
exports.RESOURCE_TYPE = 'QUEUE';
|
|
7
|
+
/**
|
|
8
|
+
* Class decorator that registers a class as an SQS queue resource.
|
|
9
|
+
*
|
|
10
|
+
* The decorated class groups one or more consumer handlers (`@Standard`
|
|
11
|
+
* or `@Fifo`) that process messages from SQS queues.
|
|
12
|
+
*
|
|
13
|
+
* @param props - Optional resource configuration (e.g. a custom `name`).
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* @Queue()
|
|
18
|
+
* export class NotificationQueue {
|
|
19
|
+
* @Standard({ batchSize: 5 })
|
|
20
|
+
* process(@Event(NotificationMessage) msg: NotificationMessage) { }
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
7
24
|
exports.Queue = (0, common_1.createResourceDecorator)({
|
|
8
25
|
type: exports.RESOURCE_TYPE,
|
|
9
26
|
callerFileIndex: 5,
|
|
@@ -50,6 +67,27 @@ const argumentParser = {
|
|
|
50
67
|
return data;
|
|
51
68
|
},
|
|
52
69
|
};
|
|
70
|
+
/**
|
|
71
|
+
* Method decorator that registers a handler as a **standard** SQS queue
|
|
72
|
+
* consumer.
|
|
73
|
+
*
|
|
74
|
+
* The decorated method becomes a Lambda function triggered by messages
|
|
75
|
+
* from a standard (non-FIFO) SQS queue. Configure delivery delay,
|
|
76
|
+
* batch size, visibility timeout, and other queue settings through
|
|
77
|
+
* the decorator props.
|
|
78
|
+
*
|
|
79
|
+
* @param props - Standard queue configuration (deliveryDelay, batchSize,
|
|
80
|
+
* visibilityTimeout, retentionPeriod, lambda, etc.).
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* @Queue()
|
|
85
|
+
* export class EmailQueue {
|
|
86
|
+
* @Standard({ batchSize: 10, visibilityTimeout: 60 })
|
|
87
|
+
* send(@Event(EmailPayload) msg: EmailPayload) { }
|
|
88
|
+
* }
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
53
91
|
exports.Standard = (0, common_1.createLambdaDecorator)({
|
|
54
92
|
getLambdaMetadata: (props, methodName) => ({
|
|
55
93
|
...props,
|
|
@@ -59,6 +97,27 @@ exports.Standard = (0, common_1.createLambdaDecorator)({
|
|
|
59
97
|
}),
|
|
60
98
|
argumentParser,
|
|
61
99
|
});
|
|
100
|
+
/**
|
|
101
|
+
* Method decorator that registers a handler as a **FIFO** SQS queue
|
|
102
|
+
* consumer.
|
|
103
|
+
*
|
|
104
|
+
* The decorated method becomes a Lambda function triggered by messages
|
|
105
|
+
* from a FIFO queue, which guarantees exactly-once processing and
|
|
106
|
+
* strict ordering. In addition to all standard queue options, FIFO
|
|
107
|
+
* queues support `contentBasedDeduplication`.
|
|
108
|
+
*
|
|
109
|
+
* @param props - FIFO queue configuration (contentBasedDeduplication,
|
|
110
|
+
* batchSize, visibilityTimeout, lambda, etc.).
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```ts
|
|
114
|
+
* @Queue()
|
|
115
|
+
* export class PaymentQueue {
|
|
116
|
+
* @Fifo({ contentBasedDeduplication: true, batchSize: 1 })
|
|
117
|
+
* process(@Event(PaymentMessage) msg: PaymentMessage) { }
|
|
118
|
+
* }
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
62
121
|
exports.Fifo = (0, common_1.createLambdaDecorator)({
|
|
63
122
|
getLambdaMetadata: (props, methodName) => ({
|
|
64
123
|
...props,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SqsQueue } from '@
|
|
1
|
+
import { SqsQueue } from '@cdktn/provider-aws/lib/sqs-queue';
|
|
2
2
|
import { type AppModule } from '@lafken/resolver';
|
|
3
3
|
import type { QueueProps } from './queue.types';
|
|
4
4
|
declare const Queue_base: (new (...args: any[]) => {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Queue = void 0;
|
|
4
|
-
const lambda_event_source_mapping_1 = require("@
|
|
5
|
-
const sqs_queue_1 = require("@
|
|
4
|
+
const lambda_event_source_mapping_1 = require("@cdktn/provider-aws/lib/lambda-event-source-mapping");
|
|
5
|
+
const sqs_queue_1 = require("@cdktn/provider-aws/lib/sqs-queue");
|
|
6
6
|
const common_1 = require("@lafken/common");
|
|
7
7
|
const resolver_1 = require("@lafken/resolver");
|
|
8
8
|
const attributeAllowedTypes = new Set(['String', 'Number']);
|
package/package.json
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lafken/queue",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
3
|
+
"version": "0.8.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Define SQS queues and consumers using TypeScript decorators - automatic infrastructure generation with Lafken",
|
|
5
6
|
"keywords": [
|
|
6
7
|
"aws",
|
|
7
8
|
"sqs",
|
|
9
|
+
"message queue",
|
|
8
10
|
"serverless",
|
|
11
|
+
"typescript",
|
|
12
|
+
"decorators",
|
|
9
13
|
"lafken"
|
|
10
14
|
],
|
|
11
|
-
"
|
|
15
|
+
"homepage": "https://github.com/Hero64/lafken#readme",
|
|
16
|
+
"bugs": "https://github.com/Hero64/lafken/issues",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/Hero64/lafken",
|
|
20
|
+
"directory": "packages/queue"
|
|
21
|
+
},
|
|
12
22
|
"license": "MIT",
|
|
23
|
+
"author": "Aníbal Jorquera",
|
|
13
24
|
"exports": {
|
|
14
25
|
"./main": {
|
|
15
26
|
"import": "./lib/main/index.js",
|
|
@@ -41,31 +52,41 @@
|
|
|
41
52
|
"lib"
|
|
42
53
|
],
|
|
43
54
|
"dependencies": {
|
|
44
|
-
"@aws-sdk/client-sqs": "3.
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"constructs": "10.4.4",
|
|
49
|
-
"reflect-metadata": "0.2.2",
|
|
50
|
-
"@lafken/common": "0.6.4",
|
|
51
|
-
"@lafken/resolver": "0.6.4"
|
|
55
|
+
"@aws-sdk/client-sqs": "^3.990.0",
|
|
56
|
+
"aws-lambda": "^1.0.7",
|
|
57
|
+
"reflect-metadata": "^0.2.2",
|
|
58
|
+
"@lafken/resolver": "0.8.0"
|
|
52
59
|
},
|
|
53
60
|
"devDependencies": {
|
|
54
|
-
"@
|
|
55
|
-
"@
|
|
56
|
-
"@
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
61
|
+
"@cdktn/provider-aws": "^23.0.0",
|
|
62
|
+
"@swc/core": "^1.15.11",
|
|
63
|
+
"@swc/helpers": "^0.5.18",
|
|
64
|
+
"@types/aws-lambda": "^8.10.160",
|
|
65
|
+
"@vitest/runner": "^4.0.18",
|
|
66
|
+
"cdktn": "^0.22.0",
|
|
67
|
+
"cdktn-vitest": "^1.0.0",
|
|
68
|
+
"constructs": "^10.4.5",
|
|
69
|
+
"unplugin-swc": "^1.5.9",
|
|
70
|
+
"vitest": "^4.0.18",
|
|
71
|
+
"@lafken/common": "0.8.0"
|
|
72
|
+
},
|
|
73
|
+
"peerDependencies": {
|
|
74
|
+
"@cdktn/provider-aws": "^23.0.0",
|
|
75
|
+
"@lafken/common": "^0.7.0",
|
|
76
|
+
"cdktn": "^0.22.0",
|
|
77
|
+
"constructs": "^10.4.5"
|
|
78
|
+
},
|
|
79
|
+
"engines": {
|
|
80
|
+
"node": ">=20.19"
|
|
60
81
|
},
|
|
61
82
|
"publishConfig": {
|
|
62
83
|
"access": "public"
|
|
63
84
|
},
|
|
64
85
|
"scripts": {
|
|
65
86
|
"build": "pnpm clean && tsc -p ./tsconfig.build.json",
|
|
87
|
+
"check-types": "tsc --noEmit -p ./tsconfig.build.json",
|
|
66
88
|
"clean": "rm -rf ./lib",
|
|
67
89
|
"dev": "tsc -w",
|
|
68
|
-
"test": "
|
|
69
|
-
"test:coverage": "jest --coverage"
|
|
90
|
+
"test": "vitest"
|
|
70
91
|
}
|
|
71
92
|
}
|