@pikku/lambda 0.6.8 → 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/CHANGELOG.md +9 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/queue/index.d.ts +1 -0
- package/dist/queue/index.js +2 -0
- package/dist/queue/index.js.map +1 -0
- package/dist/queue/sqs-worker.d.ts +4 -0
- package/dist/queue/sqs-worker.js +59 -0
- package/dist/queue/sqs-worker.js.map +1 -0
- package/package.json +4 -3
- package/src/index.ts +1 -0
- package/src/queue/index.ts +1 -0
- package/src/queue/sqs-worker.ts +97 -0
- package/tsconfig.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,sBAAsB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,sBAAsB,CAAA;AACpC,cAAc,kBAAkB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { runSQSQueueWorker } from './sqs-worker.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/queue/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { SQSBatchResponse, SQSEvent, SQSRecord } from 'aws-lambda';
|
|
2
|
+
import type { CoreSingletonServices, CreateSessionServices, QueueJob } from '@pikku/core';
|
|
3
|
+
export declare function mapSQSRecordToQueueJob(record: SQSRecord, maxAttempts?: number): QueueJob;
|
|
4
|
+
export declare const runSQSQueueWorker: (singletonServices: CoreSingletonServices, createSessionServices: CreateSessionServices<any, any, any> | undefined, event: SQSEvent) => Promise<SQSBatchResponse>;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { runQueueJob } from '@pikku/core/queue';
|
|
2
|
+
export function mapSQSRecordToQueueJob(record, maxAttempts) {
|
|
3
|
+
let data;
|
|
4
|
+
try {
|
|
5
|
+
data = JSON.parse(record.body);
|
|
6
|
+
}
|
|
7
|
+
catch {
|
|
8
|
+
data = record.body;
|
|
9
|
+
}
|
|
10
|
+
if (!record.eventSourceARN) {
|
|
11
|
+
throw new Error('SQS record does not have eventSourceARN');
|
|
12
|
+
}
|
|
13
|
+
const queueName = record.eventSourceARN.split(':').pop();
|
|
14
|
+
const job = {
|
|
15
|
+
queueName,
|
|
16
|
+
data,
|
|
17
|
+
id: record.messageId,
|
|
18
|
+
status: async () => 'active',
|
|
19
|
+
metadata: () => ({
|
|
20
|
+
processedAt: new Date(),
|
|
21
|
+
attemptsMade: parseInt(record.attributes.ApproximateReceiveCount) - 1,
|
|
22
|
+
maxAttempts,
|
|
23
|
+
result: undefined,
|
|
24
|
+
progress: 0,
|
|
25
|
+
createdAt: new Date(parseInt(record.attributes.SentTimestamp)),
|
|
26
|
+
completedAt: undefined,
|
|
27
|
+
failedAt: undefined,
|
|
28
|
+
error: undefined,
|
|
29
|
+
}),
|
|
30
|
+
waitForCompletion: async () => {
|
|
31
|
+
throw new Error('SQS does not support waitForCompletion - jobs are fire-and-forget');
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
return job;
|
|
35
|
+
}
|
|
36
|
+
export const runSQSQueueWorker = async (singletonServices, createSessionServices, event) => {
|
|
37
|
+
console.log(JSON.stringify(event, null, 2));
|
|
38
|
+
const jobs = event.Records.map(mapSQSRecordToQueueJob);
|
|
39
|
+
const results = await Promise.allSettled(jobs.map((job) => runQueueJob({
|
|
40
|
+
singletonServices,
|
|
41
|
+
createSessionServices,
|
|
42
|
+
job,
|
|
43
|
+
})));
|
|
44
|
+
results.forEach((result, index) => {
|
|
45
|
+
if (result.status === 'rejected') {
|
|
46
|
+
singletonServices.logger.error(`Failed to process SQS message ${jobs[index].id}:`, result.reason);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
return {
|
|
50
|
+
batchItemFailures: results
|
|
51
|
+
.map((result, index) => ({
|
|
52
|
+
result,
|
|
53
|
+
itemIdentifier: jobs[index].id || `message-${index}`,
|
|
54
|
+
}))
|
|
55
|
+
.filter(({ result }) => result.status === 'rejected')
|
|
56
|
+
.map(({ itemIdentifier }) => ({ itemIdentifier })),
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=sqs-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqs-worker.js","sourceRoot":"","sources":["../../src/queue/sqs-worker.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pikku/lambda",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "yasser.fadl@gmail.com",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -19,11 +19,12 @@
|
|
|
19
19
|
"exports": {
|
|
20
20
|
".": "./dist/index.js",
|
|
21
21
|
"./http": "./dist/http/index.js",
|
|
22
|
-
"./websocket": "./dist/websocket/index.js"
|
|
22
|
+
"./websocket": "./dist/websocket/index.js",
|
|
23
|
+
"./queue": "./dist/queue/index.js"
|
|
23
24
|
},
|
|
24
25
|
"peerDependencies": {
|
|
25
26
|
"@aws-sdk/client-apigatewaymanagementapi": "^3.713.0",
|
|
26
|
-
"@pikku/core": "^0.
|
|
27
|
+
"@pikku/core": "^0.8.0",
|
|
27
28
|
"@types/aws-lambda": "^8.10.146"
|
|
28
29
|
},
|
|
29
30
|
"devDependencies": {
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { runSQSQueueWorker } from './sqs-worker.js'
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { SQSBatchResponse, SQSEvent, SQSRecord } from 'aws-lambda'
|
|
2
|
+
import { runQueueJob } from '@pikku/core/queue'
|
|
3
|
+
import type {
|
|
4
|
+
CoreSingletonServices,
|
|
5
|
+
CreateSessionServices,
|
|
6
|
+
QueueJob,
|
|
7
|
+
QueueJobStatus,
|
|
8
|
+
} from '@pikku/core'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Enhanced version with additional SQS-specific features
|
|
12
|
+
*/
|
|
13
|
+
export function mapSQSRecordToQueueJob(
|
|
14
|
+
record: SQSRecord,
|
|
15
|
+
maxAttempts?: number
|
|
16
|
+
): QueueJob {
|
|
17
|
+
let data: any
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
data = JSON.parse(record.body)
|
|
21
|
+
} catch {
|
|
22
|
+
data = record.body
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (!record.eventSourceARN) {
|
|
26
|
+
throw new Error('SQS record does not have eventSourceARN')
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const queueName = record.eventSourceARN.split(':').pop()!
|
|
30
|
+
|
|
31
|
+
const job: QueueJob = {
|
|
32
|
+
queueName,
|
|
33
|
+
data,
|
|
34
|
+
id: record.messageId,
|
|
35
|
+
status: async () => 'active' as QueueJobStatus,
|
|
36
|
+
metadata: () => ({
|
|
37
|
+
processedAt: new Date(),
|
|
38
|
+
attemptsMade: parseInt(record.attributes.ApproximateReceiveCount) - 1,
|
|
39
|
+
maxAttempts,
|
|
40
|
+
result: undefined,
|
|
41
|
+
progress: 0,
|
|
42
|
+
createdAt: new Date(parseInt(record.attributes.SentTimestamp)),
|
|
43
|
+
completedAt: undefined,
|
|
44
|
+
failedAt: undefined,
|
|
45
|
+
error: undefined,
|
|
46
|
+
}),
|
|
47
|
+
waitForCompletion: async () => {
|
|
48
|
+
throw new Error(
|
|
49
|
+
'SQS does not support waitForCompletion - jobs are fire-and-forget'
|
|
50
|
+
)
|
|
51
|
+
},
|
|
52
|
+
}
|
|
53
|
+
return job
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Create an SQS handler that processes queue jobs using Pikku
|
|
58
|
+
*/
|
|
59
|
+
export const runSQSQueueWorker = async (
|
|
60
|
+
singletonServices: CoreSingletonServices,
|
|
61
|
+
createSessionServices: CreateSessionServices<any, any, any> | undefined,
|
|
62
|
+
event: SQSEvent
|
|
63
|
+
): Promise<SQSBatchResponse> => {
|
|
64
|
+
console.log(JSON.stringify(event, null, 2))
|
|
65
|
+
const jobs = event.Records.map(mapSQSRecordToQueueJob)
|
|
66
|
+
|
|
67
|
+
// Process all jobs in parallel
|
|
68
|
+
const results = await Promise.allSettled(
|
|
69
|
+
jobs.map((job) =>
|
|
70
|
+
runQueueJob({
|
|
71
|
+
singletonServices,
|
|
72
|
+
createSessionServices,
|
|
73
|
+
job,
|
|
74
|
+
})
|
|
75
|
+
)
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
// Log any failures but don't throw (SQS will handle retries)
|
|
79
|
+
results.forEach((result, index) => {
|
|
80
|
+
if (result.status === 'rejected') {
|
|
81
|
+
singletonServices.logger.error(
|
|
82
|
+
`Failed to process SQS message ${jobs[index]!.id}:`,
|
|
83
|
+
result.reason
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
batchItemFailures: results
|
|
90
|
+
.map((result, index) => ({
|
|
91
|
+
result,
|
|
92
|
+
itemIdentifier: jobs[index]!.id || `message-${index}`,
|
|
93
|
+
}))
|
|
94
|
+
.filter(({ result }) => result.status === 'rejected')
|
|
95
|
+
.map(({ itemIdentifier }) => ({ itemIdentifier })),
|
|
96
|
+
}
|
|
97
|
+
}
|
package/tsconfig.json
CHANGED
package/tsconfig.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["./src/index.ts","./src/request-converter.ts","./src/response-converter.ts","./src/http/index.ts","./src/http/run-fetch.ts","./src/websocket/index.ts","./src/websocket/lambda-channel-handler.ts","./src/websocket/lambda-eventhub-service.ts","./src/websocket/utils.ts","./src/websocket/websocket-connect.ts","./src/websocket/websocket-disconnect.ts","./src/websocket/websocket-message.ts","./src/websocket/websocket-types.ts"],"version":"5.
|
|
1
|
+
{"root":["./src/index.ts","./src/request-converter.ts","./src/response-converter.ts","./src/http/index.ts","./src/http/run-fetch.ts","./src/queue/index.ts","./src/queue/sqs-worker.ts","./src/websocket/index.ts","./src/websocket/lambda-channel-handler.ts","./src/websocket/lambda-eventhub-service.ts","./src/websocket/utils.ts","./src/websocket/websocket-connect.ts","./src/websocket/websocket-disconnect.ts","./src/websocket/websocket-message.ts","./src/websocket/websocket-types.ts"],"version":"5.8.3"}
|