@chaaskit/server 0.1.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/dist/api/admin.js +438 -0
- package/dist/api/admin.js.map +1 -0
- package/dist/api/agents.js +21 -0
- package/dist/api/agents.js.map +1 -0
- package/dist/api/api-keys.js +122 -0
- package/dist/api/api-keys.js.map +1 -0
- package/dist/api/auth.js +399 -0
- package/dist/api/auth.js.map +1 -0
- package/dist/api/chat.js +900 -0
- package/dist/api/chat.js.map +1 -0
- package/dist/api/config.js +91 -0
- package/dist/api/config.js.map +1 -0
- package/dist/api/documents.js +237 -0
- package/dist/api/documents.js.map +1 -0
- package/dist/api/export.js +107 -0
- package/dist/api/export.js.map +1 -0
- package/dist/api/health.js +25 -0
- package/dist/api/health.js.map +1 -0
- package/dist/api/mcp-server.js +84 -0
- package/dist/api/mcp-server.js.map +1 -0
- package/dist/api/mcp.js +400 -0
- package/dist/api/mcp.js.map +1 -0
- package/dist/api/mentions.js +94 -0
- package/dist/api/mentions.js.map +1 -0
- package/dist/api/oauth.js +366 -0
- package/dist/api/oauth.js.map +1 -0
- package/dist/api/payments.js +473 -0
- package/dist/api/payments.js.map +1 -0
- package/dist/api/projects.js +301 -0
- package/dist/api/projects.js.map +1 -0
- package/dist/api/scheduled-prompts.js +617 -0
- package/dist/api/scheduled-prompts.js.map +1 -0
- package/dist/api/search.js +85 -0
- package/dist/api/search.js.map +1 -0
- package/dist/api/share.js +188 -0
- package/dist/api/share.js.map +1 -0
- package/dist/api/slack.js +468 -0
- package/dist/api/slack.js.map +1 -0
- package/dist/api/teams.js +693 -0
- package/dist/api/teams.js.map +1 -0
- package/dist/api/templates.js +134 -0
- package/dist/api/templates.js.map +1 -0
- package/dist/api/threads.js +323 -0
- package/dist/api/threads.js.map +1 -0
- package/dist/api/upload.js +57 -0
- package/dist/api/upload.js.map +1 -0
- package/dist/api/user.js +111 -0
- package/dist/api/user.js.map +1 -0
- package/dist/api/v1/openai.js +245 -0
- package/dist/api/v1/openai.js.map +1 -0
- package/dist/app.js +168 -0
- package/dist/app.js.map +1 -0
- package/dist/bin/cli.js +57 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/commands/db-sync.js +108 -0
- package/dist/commands/db-sync.js.map +1 -0
- package/dist/config/loader.js +374 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/documents/extractors.js +136 -0
- package/dist/documents/extractors.js.map +1 -0
- package/dist/extensions/glob.js +53 -0
- package/dist/extensions/glob.js.map +1 -0
- package/dist/extensions/loader.js +72 -0
- package/dist/extensions/loader.js.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/loaders/index.js +75 -0
- package/dist/loaders/index.js.map +1 -0
- package/dist/mcp/client.js +551 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/server.js +335 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/middleware/apiKeyAuth.js +136 -0
- package/dist/middleware/apiKeyAuth.js.map +1 -0
- package/dist/middleware/auth.js +192 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/errorHandler.js +41 -0
- package/dist/middleware/errorHandler.js.map +1 -0
- package/dist/middleware/mcpServerAuth.js +164 -0
- package/dist/middleware/mcpServerAuth.js.map +1 -0
- package/dist/middleware/requestLogger.js +9 -0
- package/dist/middleware/requestLogger.js.map +1 -0
- package/dist/middleware/team.js +132 -0
- package/dist/middleware/team.js.map +1 -0
- package/dist/oauth/server.js +410 -0
- package/dist/oauth/server.js.map +1 -0
- package/dist/queue/cli.js +93 -0
- package/dist/queue/cli.js.map +1 -0
- package/dist/queue/handlers/index.js +91 -0
- package/dist/queue/handlers/index.js.map +1 -0
- package/dist/queue/handlers/scheduled-prompt.js +270 -0
- package/dist/queue/handlers/scheduled-prompt.js.map +1 -0
- package/dist/queue/index.js +91 -0
- package/dist/queue/index.js.map +1 -0
- package/dist/queue/providers/memory.js +296 -0
- package/dist/queue/providers/memory.js.map +1 -0
- package/dist/queue/providers/sqs.js +275 -0
- package/dist/queue/providers/sqs.js.map +1 -0
- package/dist/queue/scheduler.js +355 -0
- package/dist/queue/scheduler.js.map +1 -0
- package/dist/queue/types.js +5 -0
- package/dist/queue/types.js.map +1 -0
- package/dist/queue/worker.js +230 -0
- package/dist/queue/worker.js.map +1 -0
- package/dist/registry/index.js +40 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/server.js +207 -0
- package/dist/server.js.map +1 -0
- package/dist/services/agent.js +530 -0
- package/dist/services/agent.js.map +1 -0
- package/dist/services/agents.js +194 -0
- package/dist/services/agents.js.map +1 -0
- package/dist/services/documents.js +507 -0
- package/dist/services/documents.js.map +1 -0
- package/dist/services/email/index.js +91 -0
- package/dist/services/email/index.js.map +1 -0
- package/dist/services/email/providers/ses.js +97 -0
- package/dist/services/email/providers/ses.js.map +1 -0
- package/dist/services/email/templates.js +194 -0
- package/dist/services/email/templates.js.map +1 -0
- package/dist/services/email/types.js +5 -0
- package/dist/services/email/types.js.map +1 -0
- package/dist/services/encryption.js +69 -0
- package/dist/services/encryption.js.map +1 -0
- package/dist/services/oauth-discovery.js +226 -0
- package/dist/services/oauth-discovery.js.map +1 -0
- package/dist/services/pendingConfirmation.js +105 -0
- package/dist/services/pendingConfirmation.js.map +1 -0
- package/dist/services/scheduledPrompts.js +70 -0
- package/dist/services/scheduledPrompts.js.map +1 -0
- package/dist/services/slack/client.js +174 -0
- package/dist/services/slack/client.js.map +1 -0
- package/dist/services/slack/events.js +189 -0
- package/dist/services/slack/events.js.map +1 -0
- package/dist/services/slack/index.js +6 -0
- package/dist/services/slack/index.js.map +1 -0
- package/dist/services/slack/notifications.js +124 -0
- package/dist/services/slack/notifications.js.map +1 -0
- package/dist/services/slack/signature.js +74 -0
- package/dist/services/slack/signature.js.map +1 -0
- package/dist/services/slack/thread-context.js +191 -0
- package/dist/services/slack/thread-context.js.map +1 -0
- package/dist/services/toolConfirmation.js +55 -0
- package/dist/services/toolConfirmation.js.map +1 -0
- package/dist/services/usage.js +241 -0
- package/dist/services/usage.js.map +1 -0
- package/dist/ssr/build.js +90 -0
- package/dist/ssr/build.js.map +1 -0
- package/dist/ssr/components/SSRMessageList.js +120 -0
- package/dist/ssr/components/SSRMessageList.js.map +1 -0
- package/dist/ssr/entry.client.js +8 -0
- package/dist/ssr/entry.client.js.map +1 -0
- package/dist/ssr/entry.server.js +71 -0
- package/dist/ssr/entry.server.js.map +1 -0
- package/dist/ssr/handler.js +51 -0
- package/dist/ssr/handler.js.map +1 -0
- package/dist/ssr/root.js +184 -0
- package/dist/ssr/root.js.map +1 -0
- package/dist/ssr/routes/login.js +140 -0
- package/dist/ssr/routes/login.js.map +1 -0
- package/dist/ssr/routes/pricing.js +195 -0
- package/dist/ssr/routes/pricing.js.map +1 -0
- package/dist/ssr/routes/privacy.js +39 -0
- package/dist/ssr/routes/privacy.js.map +1 -0
- package/dist/ssr/routes/register.js +148 -0
- package/dist/ssr/routes/register.js.map +1 -0
- package/dist/ssr/routes/shared.$shareId.js +153 -0
- package/dist/ssr/routes/shared.$shareId.js.map +1 -0
- package/dist/ssr/routes/terms.js +39 -0
- package/dist/ssr/routes/terms.js.map +1 -0
- package/dist/storage/index.js +43 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/providers/database.js +38 -0
- package/dist/storage/providers/database.js.map +1 -0
- package/dist/storage/providers/filesystem.js +51 -0
- package/dist/storage/providers/filesystem.js.map +1 -0
- package/dist/storage/types.js +2 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/tools/documents.js +336 -0
- package/dist/tools/documents.js.map +1 -0
- package/dist/tools/get-plan-usage.js +82 -0
- package/dist/tools/get-plan-usage.js.map +1 -0
- package/dist/tools/index.js +106 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tools/web-scrape.js +145 -0
- package/dist/tools/web-scrape.js.map +1 -0
- package/package.json +93 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../src/queue/providers/memory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AWS SQS Queue Provider
|
|
3
|
+
*
|
|
4
|
+
* Production-ready queue provider using Amazon SQS.
|
|
5
|
+
* Features:
|
|
6
|
+
* - Long polling for efficient message retrieval
|
|
7
|
+
* - Visibility timeout for at-least-once delivery
|
|
8
|
+
* - Optional dead letter queue support
|
|
9
|
+
* - Message deduplication (for FIFO queues)
|
|
10
|
+
*
|
|
11
|
+
* Requires @aws-sdk/client-sqs to be installed:
|
|
12
|
+
* pnpm add @aws-sdk/client-sqs
|
|
13
|
+
*/
|
|
14
|
+
import { SQSClient, SendMessageCommand, ReceiveMessageCommand, DeleteMessageCommand, ChangeMessageVisibilityCommand, GetQueueAttributesCommand, } from '@aws-sdk/client-sqs';
|
|
15
|
+
import { randomUUID } from 'crypto';
|
|
16
|
+
// SQS max delay is 15 minutes (900 seconds)
|
|
17
|
+
const SQS_MAX_DELAY_SECONDS = 900;
|
|
18
|
+
/**
|
|
19
|
+
* AWS SQS Queue Provider
|
|
20
|
+
*/
|
|
21
|
+
export class SQSQueueProvider {
|
|
22
|
+
name = 'sqs';
|
|
23
|
+
client;
|
|
24
|
+
queueUrl;
|
|
25
|
+
deadLetterQueueUrl;
|
|
26
|
+
visibilityTimeout;
|
|
27
|
+
closed = false;
|
|
28
|
+
// In-memory tracking for job metadata (SQS doesn't store this)
|
|
29
|
+
jobMetadata = new Map();
|
|
30
|
+
constructor(config) {
|
|
31
|
+
this.client = new SQSClient({
|
|
32
|
+
region: config.region,
|
|
33
|
+
});
|
|
34
|
+
this.queueUrl = config.queueUrl;
|
|
35
|
+
this.deadLetterQueueUrl = config.deadLetterQueueUrl;
|
|
36
|
+
this.visibilityTimeout = config.visibilityTimeout ?? 30;
|
|
37
|
+
console.log(`[SQS] Initialized with queue: ${this.queueUrl}`);
|
|
38
|
+
}
|
|
39
|
+
async enqueue(type, payload, options) {
|
|
40
|
+
if (this.closed) {
|
|
41
|
+
throw new Error('Queue provider is closed');
|
|
42
|
+
}
|
|
43
|
+
const now = new Date();
|
|
44
|
+
const jobOptions = {
|
|
45
|
+
maxRetries: options?.maxRetries ?? 3,
|
|
46
|
+
timeout: options?.timeout ?? 30000,
|
|
47
|
+
priority: options?.priority ?? 0,
|
|
48
|
+
deduplicationKey: options?.deduplicationKey,
|
|
49
|
+
};
|
|
50
|
+
const jobId = randomUUID();
|
|
51
|
+
let delaySeconds = 0;
|
|
52
|
+
let scheduledFor;
|
|
53
|
+
let status = 'pending';
|
|
54
|
+
// Handle delay
|
|
55
|
+
if (options?.scheduledFor) {
|
|
56
|
+
const delayMs = options.scheduledFor.getTime() - now.getTime();
|
|
57
|
+
if (delayMs > 0) {
|
|
58
|
+
// SQS max delay is 15 minutes
|
|
59
|
+
if (delayMs > SQS_MAX_DELAY_SECONDS * 1000) {
|
|
60
|
+
// For longer delays, caller should use the scheduler
|
|
61
|
+
console.warn(`[SQS] Delay of ${delayMs}ms exceeds SQS max (${SQS_MAX_DELAY_SECONDS}s). ` +
|
|
62
|
+
'Consider using the scheduler for long delays.');
|
|
63
|
+
delaySeconds = SQS_MAX_DELAY_SECONDS;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
delaySeconds = Math.ceil(delayMs / 1000);
|
|
67
|
+
}
|
|
68
|
+
scheduledFor = options.scheduledFor;
|
|
69
|
+
status = 'scheduled';
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else if (options?.delay) {
|
|
73
|
+
if (options.delay > SQS_MAX_DELAY_SECONDS * 1000) {
|
|
74
|
+
console.warn(`[SQS] Delay of ${options.delay}ms exceeds SQS max (${SQS_MAX_DELAY_SECONDS}s). ` +
|
|
75
|
+
'Consider using the scheduler for long delays.');
|
|
76
|
+
delaySeconds = SQS_MAX_DELAY_SECONDS;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
delaySeconds = Math.ceil(options.delay / 1000);
|
|
80
|
+
}
|
|
81
|
+
scheduledFor = new Date(now.getTime() + delaySeconds * 1000);
|
|
82
|
+
status = delaySeconds > 0 ? 'scheduled' : 'pending';
|
|
83
|
+
}
|
|
84
|
+
// Create job metadata
|
|
85
|
+
const metadata = {
|
|
86
|
+
id: jobId,
|
|
87
|
+
type,
|
|
88
|
+
options: jobOptions,
|
|
89
|
+
status,
|
|
90
|
+
attempts: 0,
|
|
91
|
+
createdAt: now.toISOString(),
|
|
92
|
+
scheduledFor: scheduledFor?.toISOString(),
|
|
93
|
+
};
|
|
94
|
+
// Store metadata locally
|
|
95
|
+
this.jobMetadata.set(jobId, metadata);
|
|
96
|
+
// Build message body
|
|
97
|
+
const messageBody = JSON.stringify({
|
|
98
|
+
jobId,
|
|
99
|
+
type,
|
|
100
|
+
payload,
|
|
101
|
+
options: jobOptions,
|
|
102
|
+
createdAt: now.toISOString(),
|
|
103
|
+
scheduledFor: scheduledFor?.toISOString(),
|
|
104
|
+
});
|
|
105
|
+
// Send to SQS
|
|
106
|
+
const command = new SendMessageCommand({
|
|
107
|
+
QueueUrl: this.queueUrl,
|
|
108
|
+
MessageBody: messageBody,
|
|
109
|
+
DelaySeconds: delaySeconds,
|
|
110
|
+
MessageAttributes: {
|
|
111
|
+
JobId: { DataType: 'String', StringValue: jobId },
|
|
112
|
+
JobType: { DataType: 'String', StringValue: type },
|
|
113
|
+
},
|
|
114
|
+
// For FIFO queues, use deduplication key
|
|
115
|
+
...(options?.deduplicationKey && {
|
|
116
|
+
MessageDeduplicationId: options.deduplicationKey,
|
|
117
|
+
MessageGroupId: type, // Group by job type for ordering
|
|
118
|
+
}),
|
|
119
|
+
});
|
|
120
|
+
await this.client.send(command);
|
|
121
|
+
const job = {
|
|
122
|
+
id: jobId,
|
|
123
|
+
type,
|
|
124
|
+
payload,
|
|
125
|
+
options: jobOptions,
|
|
126
|
+
status,
|
|
127
|
+
attempts: 0,
|
|
128
|
+
createdAt: now,
|
|
129
|
+
scheduledFor,
|
|
130
|
+
};
|
|
131
|
+
console.log(`[SQS] Enqueued job ${jobId} (type: ${type}${delaySeconds > 0 ? `, delay: ${delaySeconds}s` : ''})`);
|
|
132
|
+
return job;
|
|
133
|
+
}
|
|
134
|
+
async receive(maxMessages = 1, waitTimeSeconds = 20) {
|
|
135
|
+
if (this.closed) {
|
|
136
|
+
return [];
|
|
137
|
+
}
|
|
138
|
+
// Long polling - blocks until messages arrive or timeout
|
|
139
|
+
const command = new ReceiveMessageCommand({
|
|
140
|
+
QueueUrl: this.queueUrl,
|
|
141
|
+
MaxNumberOfMessages: Math.min(maxMessages, 10), // SQS max is 10
|
|
142
|
+
WaitTimeSeconds: Math.min(waitTimeSeconds, 20), // SQS max is 20
|
|
143
|
+
VisibilityTimeout: this.visibilityTimeout,
|
|
144
|
+
MessageAttributeNames: ['All'],
|
|
145
|
+
MessageSystemAttributeNames: ['ApproximateReceiveCount'],
|
|
146
|
+
});
|
|
147
|
+
const response = await this.client.send(command);
|
|
148
|
+
if (!response.Messages || response.Messages.length === 0) {
|
|
149
|
+
return [];
|
|
150
|
+
}
|
|
151
|
+
const jobs = [];
|
|
152
|
+
for (const message of response.Messages) {
|
|
153
|
+
try {
|
|
154
|
+
const job = this.parseMessage(message);
|
|
155
|
+
if (job) {
|
|
156
|
+
jobs.push(job);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
console.error('[SQS] Failed to parse message:', error);
|
|
161
|
+
// Delete malformed message to prevent infinite retries
|
|
162
|
+
if (message.ReceiptHandle) {
|
|
163
|
+
try {
|
|
164
|
+
await this.deleteMessage(message.ReceiptHandle);
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
// Ignore deletion errors
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return jobs;
|
|
173
|
+
}
|
|
174
|
+
async acknowledge(receiptHandle) {
|
|
175
|
+
await this.deleteMessage(receiptHandle);
|
|
176
|
+
console.log('[SQS] Acknowledged message');
|
|
177
|
+
}
|
|
178
|
+
async fail(receiptHandle, error) {
|
|
179
|
+
// Make message visible again immediately for retry
|
|
180
|
+
// The retry delay is handled by SQS's built-in retry mechanism
|
|
181
|
+
try {
|
|
182
|
+
const command = new ChangeMessageVisibilityCommand({
|
|
183
|
+
QueueUrl: this.queueUrl,
|
|
184
|
+
ReceiptHandle: receiptHandle,
|
|
185
|
+
VisibilityTimeout: 0, // Make visible immediately
|
|
186
|
+
});
|
|
187
|
+
await this.client.send(command);
|
|
188
|
+
console.log('[SQS] Failed message, returning to queue:', error.message);
|
|
189
|
+
}
|
|
190
|
+
catch (sqsError) {
|
|
191
|
+
// If changing visibility fails, the message will eventually become visible again
|
|
192
|
+
console.error('[SQS] Failed to change message visibility:', sqsError);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
async getJob(jobId) {
|
|
196
|
+
// SQS doesn't support fetching by ID, use local metadata
|
|
197
|
+
const metadata = this.jobMetadata.get(jobId);
|
|
198
|
+
if (!metadata) {
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
id: metadata.id,
|
|
203
|
+
type: metadata.type,
|
|
204
|
+
payload: null, // Payload not stored in metadata
|
|
205
|
+
options: metadata.options,
|
|
206
|
+
status: metadata.status,
|
|
207
|
+
attempts: metadata.attempts,
|
|
208
|
+
createdAt: new Date(metadata.createdAt),
|
|
209
|
+
scheduledFor: metadata.scheduledFor ? new Date(metadata.scheduledFor) : undefined,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
async getStats() {
|
|
213
|
+
try {
|
|
214
|
+
const command = new GetQueueAttributesCommand({
|
|
215
|
+
QueueUrl: this.queueUrl,
|
|
216
|
+
AttributeNames: [
|
|
217
|
+
'ApproximateNumberOfMessages',
|
|
218
|
+
'ApproximateNumberOfMessagesNotVisible',
|
|
219
|
+
'ApproximateNumberOfMessagesDelayed',
|
|
220
|
+
],
|
|
221
|
+
});
|
|
222
|
+
const response = await this.client.send(command);
|
|
223
|
+
const attrs = response.Attributes || {};
|
|
224
|
+
return {
|
|
225
|
+
pending: parseInt(attrs.ApproximateNumberOfMessages || '0', 10),
|
|
226
|
+
processing: parseInt(attrs.ApproximateNumberOfMessagesNotVisible || '0', 10),
|
|
227
|
+
scheduled: parseInt(attrs.ApproximateNumberOfMessagesDelayed || '0', 10),
|
|
228
|
+
completed: 0, // SQS doesn't track completed
|
|
229
|
+
failed: 0, // Would need DLQ stats
|
|
230
|
+
dead: 0,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
console.error('[SQS] Failed to get queue stats:', error);
|
|
235
|
+
return { pending: 0, processing: 0, completed: 0, failed: 0, dead: 0, scheduled: 0 };
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
async close() {
|
|
239
|
+
this.closed = true;
|
|
240
|
+
this.client.destroy();
|
|
241
|
+
console.log('[SQS] Provider closed');
|
|
242
|
+
}
|
|
243
|
+
async deleteMessage(receiptHandle) {
|
|
244
|
+
const command = new DeleteMessageCommand({
|
|
245
|
+
QueueUrl: this.queueUrl,
|
|
246
|
+
ReceiptHandle: receiptHandle,
|
|
247
|
+
});
|
|
248
|
+
await this.client.send(command);
|
|
249
|
+
}
|
|
250
|
+
parseMessage(message) {
|
|
251
|
+
if (!message.Body || !message.ReceiptHandle) {
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
const body = JSON.parse(message.Body);
|
|
255
|
+
const receiveCount = parseInt(message.Attributes?.ApproximateReceiveCount || '1', 10);
|
|
256
|
+
// Update local metadata
|
|
257
|
+
const metadata = this.jobMetadata.get(body.jobId);
|
|
258
|
+
if (metadata) {
|
|
259
|
+
metadata.attempts = receiveCount;
|
|
260
|
+
metadata.status = 'processing';
|
|
261
|
+
}
|
|
262
|
+
return {
|
|
263
|
+
id: body.jobId,
|
|
264
|
+
type: body.type,
|
|
265
|
+
payload: body.payload,
|
|
266
|
+
options: body.options,
|
|
267
|
+
status: 'processing',
|
|
268
|
+
attempts: receiveCount,
|
|
269
|
+
createdAt: new Date(body.createdAt),
|
|
270
|
+
scheduledFor: body.scheduledFor ? new Date(body.scheduledFor) : undefined,
|
|
271
|
+
receiptHandle: message.ReceiptHandle,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
//# sourceMappingURL=sqs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqs.js","sourceRoot":"","sources":["../../../src/queue/providers/sqs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Queue Scheduler
|
|
3
|
+
*
|
|
4
|
+
* Database-backed scheduler for delayed and recurring jobs.
|
|
5
|
+
* - One-time scheduled jobs: stored in ScheduledJob table, enqueued when due
|
|
6
|
+
* - Recurring jobs: stored in RecurringJob table, enqueued on schedule
|
|
7
|
+
*
|
|
8
|
+
* Supports both cron expressions and interval syntax.
|
|
9
|
+
*/
|
|
10
|
+
import { db } from '@chaaskit/db';
|
|
11
|
+
import { CronExpressionParser } from 'cron-parser';
|
|
12
|
+
/**
|
|
13
|
+
* Parse an interval string like "every 5 minutes" into milliseconds
|
|
14
|
+
*/
|
|
15
|
+
function parseInterval(schedule) {
|
|
16
|
+
const match = schedule.match(/^every\s+(\d+)\s+(second|minute|hour|day|week)s?$/i);
|
|
17
|
+
if (!match)
|
|
18
|
+
return null;
|
|
19
|
+
const value = parseInt(match[1], 10);
|
|
20
|
+
const unit = match[2].toLowerCase();
|
|
21
|
+
const multipliers = {
|
|
22
|
+
second: 1000,
|
|
23
|
+
minute: 60 * 1000,
|
|
24
|
+
hour: 60 * 60 * 1000,
|
|
25
|
+
day: 24 * 60 * 60 * 1000,
|
|
26
|
+
week: 7 * 24 * 60 * 60 * 1000,
|
|
27
|
+
};
|
|
28
|
+
return value * (multipliers[unit] || 0);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Calculate the next run time for a schedule
|
|
32
|
+
*/
|
|
33
|
+
function calculateNextRun(schedule, timezone, fromDate) {
|
|
34
|
+
// Try interval syntax first
|
|
35
|
+
const intervalMs = parseInterval(schedule);
|
|
36
|
+
if (intervalMs !== null) {
|
|
37
|
+
const from = fromDate || new Date();
|
|
38
|
+
return new Date(from.getTime() + intervalMs);
|
|
39
|
+
}
|
|
40
|
+
// Parse as cron expression
|
|
41
|
+
try {
|
|
42
|
+
const options = {
|
|
43
|
+
currentDate: fromDate || new Date(),
|
|
44
|
+
tz: timezone,
|
|
45
|
+
};
|
|
46
|
+
const interval = CronExpressionParser.parse(schedule, options);
|
|
47
|
+
return interval.next().toDate();
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
throw new Error(`Invalid schedule format: "${schedule}". Use cron expression (e.g., "0 9 * * *") ` +
|
|
51
|
+
`or interval (e.g., "every 5 minutes")`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Scheduler for delayed and recurring jobs.
|
|
56
|
+
*/
|
|
57
|
+
export class Scheduler {
|
|
58
|
+
provider;
|
|
59
|
+
pollInterval;
|
|
60
|
+
running = false;
|
|
61
|
+
pollTimer = null;
|
|
62
|
+
constructor(options) {
|
|
63
|
+
this.provider = options.provider;
|
|
64
|
+
this.pollInterval = options.config.pollInterval ?? 60000;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Start the scheduler.
|
|
68
|
+
*/
|
|
69
|
+
async start() {
|
|
70
|
+
if (this.running) {
|
|
71
|
+
console.warn('[Scheduler] Already running');
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
this.running = true;
|
|
75
|
+
console.log(`[Scheduler] Starting with poll interval ${this.pollInterval}ms`);
|
|
76
|
+
// Run immediately on start
|
|
77
|
+
await this.poll();
|
|
78
|
+
// Schedule periodic polling
|
|
79
|
+
this.pollTimer = setInterval(async () => {
|
|
80
|
+
try {
|
|
81
|
+
await this.poll();
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
console.error('[Scheduler] Error during poll:', error);
|
|
85
|
+
}
|
|
86
|
+
}, this.pollInterval);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Stop the scheduler.
|
|
90
|
+
*/
|
|
91
|
+
async stop() {
|
|
92
|
+
if (!this.running) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
console.log('[Scheduler] Stopping...');
|
|
96
|
+
this.running = false;
|
|
97
|
+
if (this.pollTimer) {
|
|
98
|
+
clearInterval(this.pollTimer);
|
|
99
|
+
this.pollTimer = null;
|
|
100
|
+
}
|
|
101
|
+
console.log('[Scheduler] Stopped');
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Schedule a one-time job for future execution.
|
|
105
|
+
*/
|
|
106
|
+
async schedule(type, payload, scheduledFor, options) {
|
|
107
|
+
console.log(`[Scheduler] Scheduling job ${type} for ${scheduledFor.toISOString()}`);
|
|
108
|
+
const job = await db.scheduledJob.create({
|
|
109
|
+
data: {
|
|
110
|
+
type,
|
|
111
|
+
payload: JSON.stringify(payload),
|
|
112
|
+
options: JSON.stringify(options || {}),
|
|
113
|
+
scheduledFor,
|
|
114
|
+
status: 'scheduled',
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
return job;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Cancel a scheduled job.
|
|
121
|
+
*/
|
|
122
|
+
async cancelScheduledJob(jobId) {
|
|
123
|
+
const result = await db.scheduledJob.updateMany({
|
|
124
|
+
where: {
|
|
125
|
+
id: jobId,
|
|
126
|
+
status: 'scheduled',
|
|
127
|
+
},
|
|
128
|
+
data: {
|
|
129
|
+
status: 'cancelled',
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
return result.count > 0;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Register or update a recurring job.
|
|
136
|
+
*/
|
|
137
|
+
async registerRecurring(input) {
|
|
138
|
+
// Validate schedule by calculating next run
|
|
139
|
+
const nextRunAt = calculateNextRun(input.schedule, input.timezone || 'UTC');
|
|
140
|
+
console.log(`[Scheduler] Registering recurring job "${input.name}" with schedule "${input.schedule}", ` +
|
|
141
|
+
`next run: ${nextRunAt.toISOString()}`);
|
|
142
|
+
const job = await db.recurringJob.upsert({
|
|
143
|
+
where: { name: input.name },
|
|
144
|
+
create: {
|
|
145
|
+
name: input.name,
|
|
146
|
+
type: input.type,
|
|
147
|
+
payload: JSON.stringify(input.payload),
|
|
148
|
+
options: JSON.stringify(input.options || {}),
|
|
149
|
+
schedule: input.schedule,
|
|
150
|
+
timezone: input.timezone || 'UTC',
|
|
151
|
+
enabled: true,
|
|
152
|
+
nextRunAt,
|
|
153
|
+
},
|
|
154
|
+
update: {
|
|
155
|
+
type: input.type,
|
|
156
|
+
payload: JSON.stringify(input.payload),
|
|
157
|
+
options: JSON.stringify(input.options || {}),
|
|
158
|
+
schedule: input.schedule,
|
|
159
|
+
timezone: input.timezone || 'UTC',
|
|
160
|
+
enabled: true,
|
|
161
|
+
nextRunAt,
|
|
162
|
+
lastError: null,
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
return job;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Disable a recurring job.
|
|
169
|
+
*/
|
|
170
|
+
async disableRecurring(name) {
|
|
171
|
+
const result = await db.recurringJob.updateMany({
|
|
172
|
+
where: { name },
|
|
173
|
+
data: { enabled: false },
|
|
174
|
+
});
|
|
175
|
+
return result.count > 0;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Enable a recurring job.
|
|
179
|
+
*/
|
|
180
|
+
async enableRecurring(name) {
|
|
181
|
+
const job = await db.recurringJob.findUnique({ where: { name } });
|
|
182
|
+
if (!job)
|
|
183
|
+
return false;
|
|
184
|
+
const nextRunAt = calculateNextRun(job.schedule, job.timezone);
|
|
185
|
+
await db.recurringJob.update({
|
|
186
|
+
where: { name },
|
|
187
|
+
data: {
|
|
188
|
+
enabled: true,
|
|
189
|
+
nextRunAt,
|
|
190
|
+
lastError: null,
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Delete a recurring job.
|
|
197
|
+
*/
|
|
198
|
+
async deleteRecurring(name) {
|
|
199
|
+
const result = await db.recurringJob.deleteMany({
|
|
200
|
+
where: { name },
|
|
201
|
+
});
|
|
202
|
+
return result.count > 0;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Get all recurring jobs.
|
|
206
|
+
*/
|
|
207
|
+
async listRecurring() {
|
|
208
|
+
return db.recurringJob.findMany({
|
|
209
|
+
orderBy: { name: 'asc' },
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Poll for due jobs and enqueue them.
|
|
214
|
+
*/
|
|
215
|
+
async poll() {
|
|
216
|
+
const now = new Date();
|
|
217
|
+
// Process one-time scheduled jobs
|
|
218
|
+
await this.processScheduledJobs(now);
|
|
219
|
+
// Process recurring jobs
|
|
220
|
+
await this.processRecurringJobs(now);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Process one-time scheduled jobs that are due.
|
|
224
|
+
*/
|
|
225
|
+
async processScheduledJobs(now) {
|
|
226
|
+
// Find jobs that are due
|
|
227
|
+
const dueJobs = await db.scheduledJob.findMany({
|
|
228
|
+
where: {
|
|
229
|
+
status: 'scheduled',
|
|
230
|
+
scheduledFor: { lte: now },
|
|
231
|
+
},
|
|
232
|
+
take: 100, // Process in batches
|
|
233
|
+
});
|
|
234
|
+
for (const job of dueJobs) {
|
|
235
|
+
try {
|
|
236
|
+
const payload = JSON.parse(job.payload);
|
|
237
|
+
const options = JSON.parse(job.options);
|
|
238
|
+
await this.provider.enqueue(job.type, payload, options);
|
|
239
|
+
await db.scheduledJob.update({
|
|
240
|
+
where: { id: job.id },
|
|
241
|
+
data: { status: 'enqueued' },
|
|
242
|
+
});
|
|
243
|
+
console.log(`[Scheduler] Enqueued scheduled job ${job.id} (type: ${job.type})`);
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
247
|
+
console.error(`[Scheduler] Failed to enqueue scheduled job ${job.id}:`, errorMessage);
|
|
248
|
+
await db.scheduledJob.update({
|
|
249
|
+
where: { id: job.id },
|
|
250
|
+
data: {
|
|
251
|
+
status: 'scheduled', // Keep it scheduled for retry
|
|
252
|
+
error: errorMessage,
|
|
253
|
+
},
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Process recurring jobs that are due.
|
|
260
|
+
*/
|
|
261
|
+
async processRecurringJobs(now) {
|
|
262
|
+
// Find recurring jobs that are due
|
|
263
|
+
const dueJobs = await db.recurringJob.findMany({
|
|
264
|
+
where: {
|
|
265
|
+
enabled: true,
|
|
266
|
+
nextRunAt: { lte: now },
|
|
267
|
+
},
|
|
268
|
+
});
|
|
269
|
+
for (const job of dueJobs) {
|
|
270
|
+
try {
|
|
271
|
+
const payload = JSON.parse(job.payload);
|
|
272
|
+
const options = JSON.parse(job.options);
|
|
273
|
+
await this.provider.enqueue(job.type, payload, options);
|
|
274
|
+
// Calculate next run time
|
|
275
|
+
const nextRunAt = calculateNextRun(job.schedule, job.timezone, now);
|
|
276
|
+
await db.recurringJob.update({
|
|
277
|
+
where: { id: job.id },
|
|
278
|
+
data: {
|
|
279
|
+
lastRunAt: now,
|
|
280
|
+
nextRunAt,
|
|
281
|
+
lastError: null,
|
|
282
|
+
},
|
|
283
|
+
});
|
|
284
|
+
console.log(`[Scheduler] Enqueued recurring job "${job.name}" (type: ${job.type}), ` +
|
|
285
|
+
`next run: ${nextRunAt.toISOString()}`);
|
|
286
|
+
}
|
|
287
|
+
catch (error) {
|
|
288
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
289
|
+
console.error(`[Scheduler] Failed to enqueue recurring job "${job.name}":`, errorMessage);
|
|
290
|
+
// Still calculate next run, but store the error
|
|
291
|
+
let nextRunAt;
|
|
292
|
+
try {
|
|
293
|
+
nextRunAt = calculateNextRun(job.schedule, job.timezone, now);
|
|
294
|
+
}
|
|
295
|
+
catch {
|
|
296
|
+
// If schedule is invalid, disable the job
|
|
297
|
+
await db.recurringJob.update({
|
|
298
|
+
where: { id: job.id },
|
|
299
|
+
data: {
|
|
300
|
+
enabled: false,
|
|
301
|
+
lastError: `Invalid schedule: ${errorMessage}`,
|
|
302
|
+
},
|
|
303
|
+
});
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
await db.recurringJob.update({
|
|
307
|
+
where: { id: job.id },
|
|
308
|
+
data: {
|
|
309
|
+
nextRunAt,
|
|
310
|
+
lastError: errorMessage,
|
|
311
|
+
},
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
// Singleton scheduler instance
|
|
318
|
+
let schedulerInstance = null;
|
|
319
|
+
/**
|
|
320
|
+
* Get or create the scheduler singleton.
|
|
321
|
+
*/
|
|
322
|
+
export function getScheduler(options) {
|
|
323
|
+
if (!schedulerInstance && options) {
|
|
324
|
+
schedulerInstance = new Scheduler(options);
|
|
325
|
+
}
|
|
326
|
+
return schedulerInstance;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Start the scheduler with the given options.
|
|
330
|
+
*/
|
|
331
|
+
export async function startScheduler(options) {
|
|
332
|
+
if (schedulerInstance) {
|
|
333
|
+
console.warn('[Scheduler] Scheduler already exists');
|
|
334
|
+
return schedulerInstance;
|
|
335
|
+
}
|
|
336
|
+
schedulerInstance = new Scheduler(options);
|
|
337
|
+
await schedulerInstance.start();
|
|
338
|
+
return schedulerInstance;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Stop the scheduler.
|
|
342
|
+
*/
|
|
343
|
+
export async function stopScheduler() {
|
|
344
|
+
if (schedulerInstance) {
|
|
345
|
+
await schedulerInstance.stop();
|
|
346
|
+
schedulerInstance = null;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Reset the scheduler singleton (for testing).
|
|
351
|
+
*/
|
|
352
|
+
export function resetScheduler() {
|
|
353
|
+
schedulerInstance = null;
|
|
354
|
+
}
|
|
355
|
+
//# sourceMappingURL=scheduler.js.map
|