bunqueue 2.9.0 → 2.9.2
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 +7 -3
- package/dist/application/background/recovery/active.d.ts +1 -0
- package/dist/application/background/recovery/active.js +12 -0
- package/dist/application/background/recovery/index.js +3 -1
- package/dist/application/background/recovery/pending.js +1 -0
- package/dist/application/cleanupTasks.js +4 -16
- package/dist/application/contextFactory.js +3 -0
- package/dist/application/dlqManager.js +1 -0
- package/dist/application/dlqRetry.js +1 -0
- package/dist/application/eventsManager.d.ts +8 -1
- package/dist/application/eventsManager.js +76 -29
- package/dist/application/operations/ackHelpers.d.ts +1 -4
- package/dist/application/operations/ackHelpers.js +39 -14
- package/dist/application/operations/flowPush.js +1 -0
- package/dist/application/operations/flowValidation.js +4 -4
- package/dist/application/operations/pull.d.ts +7 -2
- package/dist/application/operations/pull.js +15 -57
- package/dist/application/operations/pullFinalization.d.ts +6 -0
- package/dist/application/operations/pullFinalization.js +69 -0
- package/dist/application/operations/pullStateTransition.d.ts +8 -7
- package/dist/application/operations/pullStateTransition.js +25 -18
- package/dist/application/operations/push.js +3 -0
- package/dist/application/operations/pushBatch.js +14 -7
- package/dist/application/operations/pushContext.d.ts +2 -1
- package/dist/application/postgres-queue-manager/control.d.ts +4 -0
- package/dist/application/postgres-queue-manager/control.js +24 -0
- package/dist/application/postgres-queue-manager/delivery.d.ts +5 -4
- package/dist/application/postgres-queue-manager/delivery.js +13 -10
- package/dist/application/postgres-queue-manager/groupQueries.d.ts +10 -0
- package/dist/application/postgres-queue-manager/groupQueries.js +40 -0
- package/dist/application/postgres-queue-manager/queries.d.ts +2 -2
- package/dist/application/postgres-queue-manager/queries.js +2 -2
- package/dist/application/queue-manager/control.js +1 -0
- package/dist/application/queue-manager/delivery.d.ts +5 -4
- package/dist/application/queue-manager/delivery.js +15 -8
- package/dist/application/queue-manager/limits.d.ts +11 -0
- package/dist/application/queue-manager/limits.js +61 -0
- package/dist/application/queue-manager/state.js +1 -1
- package/dist/application/queueTelemetryJournal.d.ts +2 -0
- package/dist/application/queueTelemetryJournal.js +23 -0
- package/dist/application/types/ack.d.ts +3 -1
- package/dist/cli/commandRouter.d.ts +1 -1
- package/dist/client/flowPush.js +6 -0
- package/dist/client/groupId.d.ts +1 -0
- package/dist/client/groupId.js +1 -0
- package/dist/client/index.d.ts +1 -1
- package/dist/client/jobHelpers.js +1 -0
- package/dist/client/queue/operations/add/bulk.js +4 -4
- package/dist/client/queue/operations/add/payload.d.ts +1 -0
- package/dist/client/queue/operations/add/payload.js +7 -1
- package/dist/client/queue/operations/add/single.js +3 -3
- package/dist/client/queue/operations/groups.d.ts +21 -0
- package/dist/client/queue/operations/groups.js +88 -0
- package/dist/client/queue/runtime/queries.d.ts +13 -0
- package/dist/client/queue/runtime/queries.js +31 -0
- package/dist/client/queue/runtime/state.d.ts +4 -0
- package/dist/client/queue/runtime/state.js +1 -0
- package/dist/client/types/index.d.ts +2 -2
- package/dist/client/types/options.d.ts +4 -0
- package/dist/client/types/worker.d.ts +8 -0
- package/dist/client/worker/runtime/execution.js +1 -0
- package/dist/client/worker/runtime/options.js +3 -0
- package/dist/client/worker/types/options.d.ts +2 -1
- package/dist/client/worker/workerPull.d.ts +2 -0
- package/dist/client/worker/workerPull.js +6 -4
- package/dist/domain/job/groupFifoOrder.d.ts +9 -0
- package/dist/domain/job/groupFifoOrder.js +26 -0
- package/dist/domain/queue/groupLimiterManager.d.ts +23 -0
- package/dist/domain/queue/groupLimiterManager.js +107 -0
- package/dist/domain/queue/groupScheduler.d.ts +31 -0
- package/dist/domain/queue/groupScheduler.js +256 -0
- package/dist/domain/queue/groupSchedulerOrder.d.ts +6 -0
- package/dist/domain/queue/groupSchedulerOrder.js +30 -0
- package/dist/domain/queue/priorityQueue.d.ts +13 -23
- package/dist/domain/queue/priorityQueue.js +53 -42
- package/dist/domain/queue/shard/keys.d.ts +1 -0
- package/dist/domain/queue/shard/keys.js +25 -2
- package/dist/domain/queue/shard/lifecycle.js +4 -0
- package/dist/domain/queue/shard/limits.d.ts +20 -1
- package/dist/domain/queue/shard/limits.js +56 -0
- package/dist/domain/queue/shard/state.d.ts +5 -0
- package/dist/domain/queue/shard/state.js +9 -1
- package/dist/domain/types/commands/core.d.ts +3 -0
- package/dist/domain/types/commands/limits.d.ts +41 -0
- package/dist/domain/types/commands/union.d.ts +1 -1
- package/dist/domain/types/group.d.ts +21 -0
- package/dist/domain/types/group.js +78 -0
- package/dist/domain/types/priorityQueue.d.ts +1 -0
- package/dist/infrastructure/persistence/jobOptionsBlob.d.ts +1 -0
- package/dist/infrastructure/persistence/jobOptionsBlob.js +10 -2
- package/dist/infrastructure/persistence/migrations.js +11 -0
- package/dist/infrastructure/persistence/postgres/admission.js +5 -2
- package/dist/infrastructure/persistence/postgres/batchAdmission.js +22 -4
- package/dist/infrastructure/persistence/postgres/claimBatch.d.ts +3 -0
- package/dist/infrastructure/persistence/postgres/claimBatch.js +16 -3
- package/dist/infrastructure/persistence/postgres/claimSelection.d.ts +8 -1
- package/dist/infrastructure/persistence/postgres/claimSelection.js +73 -131
- package/dist/infrastructure/persistence/postgres/claims.d.ts +8 -1
- package/dist/infrastructure/persistence/postgres/claims.js +19 -3
- package/dist/infrastructure/persistence/postgres/eventCatchupCursors.d.ts +32 -0
- package/dist/infrastructure/persistence/postgres/eventCatchupCursors.js +66 -0
- package/dist/infrastructure/persistence/postgres/eventJournalSchema.d.ts +2 -2
- package/dist/infrastructure/persistence/postgres/eventJournalSchema.js +16 -2
- package/dist/infrastructure/persistence/postgres/eventPruneWatermarks.d.ts +2 -0
- package/dist/infrastructure/persistence/postgres/eventPruneWatermarks.js +21 -3
- package/dist/infrastructure/persistence/postgres/events.d.ts +3 -3
- package/dist/infrastructure/persistence/postgres/events.js +44 -17
- package/dist/infrastructure/persistence/postgres/groupClaims.d.ts +15 -0
- package/dist/infrastructure/persistence/postgres/groupClaims.js +95 -0
- package/dist/infrastructure/persistence/postgres/groupSchema.d.ts +2 -0
- package/dist/infrastructure/persistence/postgres/groupSchema.js +155 -0
- package/dist/infrastructure/persistence/postgres/groupSchemaFingerprint.d.ts +3 -0
- package/dist/infrastructure/persistence/postgres/groupSchemaFingerprint.js +127 -0
- package/dist/infrastructure/persistence/postgres/groupStateRetention.d.ts +3 -0
- package/dist/infrastructure/persistence/postgres/groupStateRetention.js +93 -0
- package/dist/infrastructure/persistence/postgres/groups.d.ts +11 -0
- package/dist/infrastructure/persistence/postgres/groups.js +117 -0
- package/dist/infrastructure/persistence/postgres/queueDestruction.js +4 -0
- package/dist/infrastructure/persistence/postgres/runtime.d.ts +0 -1
- package/dist/infrastructure/persistence/postgres/runtime.js +3 -1
- package/dist/infrastructure/persistence/postgres/schema.d.ts +2 -2
- package/dist/infrastructure/persistence/postgres/schema.js +8 -4
- package/dist/infrastructure/persistence/postgres/schemaInitialization.js +6 -1
- package/dist/infrastructure/persistence/postgres/store.d.ts +11 -1
- package/dist/infrastructure/persistence/postgres/store.js +47 -3
- package/dist/infrastructure/persistence/postgres/telemetry.d.ts +2 -0
- package/dist/infrastructure/persistence/postgres/telemetry.js +33 -21
- package/dist/infrastructure/persistence/postgres/types.d.ts +1 -0
- package/dist/infrastructure/persistence/schema.d.ts +2 -2
- package/dist/infrastructure/persistence/schema.js +12 -1
- package/dist/infrastructure/persistence/sqlite/control.d.ts +14 -0
- package/dist/infrastructure/persistence/sqlite/control.js +69 -0
- package/dist/infrastructure/persistence/sqlite/jobs.d.ts +12 -0
- package/dist/infrastructure/persistence/sqlite/jobs.js +36 -0
- package/dist/infrastructure/persistence/sqlite/telemetry.d.ts +2 -1
- package/dist/infrastructure/persistence/sqlite/telemetry.js +5 -64
- package/dist/infrastructure/persistence/sqlite/telemetryWrites.d.ts +4 -0
- package/dist/infrastructure/persistence/sqlite/telemetryWrites.js +123 -0
- package/dist/infrastructure/persistence/sqliteSerializer.js +2 -0
- package/dist/infrastructure/server/handler-routes/control.js +13 -0
- package/dist/infrastructure/server/handlers/core.d.ts +0 -5
- package/dist/infrastructure/server/handlers/core.js +15 -18
- package/dist/infrastructure/server/handlers/groups.d.ts +11 -0
- package/dist/infrastructure/server/handlers/groups.js +55 -0
- package/dist/infrastructure/server/handlers/pushBatchValidation.js +4 -1
- package/dist/infrastructure/server/protocol/validation.d.ts +1 -0
- package/dist/infrastructure/server/protocol/validation.js +1 -0
- package/dist/infrastructure/server/protocol.d.ts +1 -1
- package/dist/infrastructure/server/protocol.js +1 -1
- package/package.json +2 -1
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { jobId } from '../../domain/types/job';
|
|
7
7
|
import { setDlqRetryState } from '../../domain/types/dlq';
|
|
8
8
|
import { normalizeLegacyJobPayload } from '../../domain/job/payload';
|
|
9
|
+
import { restoreGroupFifoOrder } from '../../domain/job/groupFifoOrder';
|
|
9
10
|
import { decodeJobOptions } from './jobOptionsBlob';
|
|
10
11
|
import { storageLog } from '../../shared/logger';
|
|
11
12
|
import { decodeMessagePack as msgpackDecode, encodeMessagePack as msgpackEncode, } from '../../shared/msgpack';
|
|
@@ -166,6 +167,7 @@ export function rowToJob(row) {
|
|
|
166
167
|
? unpack(row.stacktrace, null, `${jobContext}:stacktrace`)
|
|
167
168
|
: null,
|
|
168
169
|
};
|
|
170
|
+
restoreGroupFifoOrder(job, extended.groupFifoOrder);
|
|
169
171
|
const dlqRetryState = row.dlq_retry_state
|
|
170
172
|
? unpack(row.dlq_retry_state, null, `${jobContext}:dlqRetryState`)
|
|
171
173
|
: null;
|
|
@@ -2,6 +2,7 @@ import { handleClean, handleClearConcurrency, handleGetDlqConfig, handleGetStall
|
|
|
2
2
|
import { handleCron, handleCronDelete, handleCronGet, handleCronList } from '../handlers/cron';
|
|
3
3
|
import { handleDlq, handleGetDlqStats, handlePurgeDlq, handleRemoveDlqJob, handleRetryCompleted, handleRetryDlq, } from '../handlers/dlq';
|
|
4
4
|
import { handleDrain, handlePause, handleResume } from '../handlers/management';
|
|
5
|
+
import { handleGroupCommand, handleGroupsJobsCount } from '../handlers/groups';
|
|
5
6
|
export function routeQueueControlCommand(command, context, requestId) {
|
|
6
7
|
switch (command.cmd) {
|
|
7
8
|
case 'Pause':
|
|
@@ -42,6 +43,18 @@ export function routeDlqCommand(command, context, requestId) {
|
|
|
42
43
|
}
|
|
43
44
|
export function routeRateLimitCommand(command, context, requestId) {
|
|
44
45
|
switch (command.cmd) {
|
|
46
|
+
case 'GetGroupsJobsCount':
|
|
47
|
+
return handleGroupsJobsCount(command, context, requestId);
|
|
48
|
+
case 'GetGroupJobsCount':
|
|
49
|
+
case 'GetGroupActiveCount':
|
|
50
|
+
case 'SetGroupRateLimit':
|
|
51
|
+
case 'GetGroupRateLimit':
|
|
52
|
+
case 'RemoveGroupRateLimit':
|
|
53
|
+
case 'GetGroupRateLimitTtl':
|
|
54
|
+
case 'SetGroupConcurrency':
|
|
55
|
+
case 'GetGroupConcurrency':
|
|
56
|
+
case 'RemoveGroupConcurrency':
|
|
57
|
+
return handleGroupCommand(command, context, requestId);
|
|
45
58
|
case 'RateLimit':
|
|
46
59
|
return handleRateLimit(command, context, requestId);
|
|
47
60
|
case 'RateLimitClear':
|
|
@@ -1,20 +1,15 @@
|
|
|
1
|
-
/** Core command handlers for push, pull, acknowledgement, and failure. */
|
|
2
1
|
import type { Command } from '../../../domain/types/command';
|
|
3
2
|
import type { Response } from '../../../domain/types/response';
|
|
4
3
|
import type { HandlerContext } from '../types';
|
|
5
|
-
/** Handle PUSH command */
|
|
6
4
|
export declare function handlePush(cmd: Extract<Command, {
|
|
7
5
|
cmd: 'PUSH';
|
|
8
6
|
}>, ctx: HandlerContext, reqId?: string): Promise<Response>;
|
|
9
|
-
/** Handle PUSHB (batch push) command */
|
|
10
7
|
export declare function handlePushBatch(cmd: Extract<Command, {
|
|
11
8
|
cmd: 'PUSHB';
|
|
12
9
|
}>, ctx: HandlerContext, reqId?: string): Promise<Response>;
|
|
13
|
-
/** Handle PULL command */
|
|
14
10
|
export declare function handlePull(cmd: Extract<Command, {
|
|
15
11
|
cmd: 'PULL';
|
|
16
12
|
}>, ctx: HandlerContext, reqId?: string): Promise<Response>;
|
|
17
|
-
/** Handle PULLB (batch pull) command - uses optimized single-lock batch pull */
|
|
18
13
|
export declare function handlePullBatch(cmd: Extract<Command, {
|
|
19
14
|
cmd: 'PULLB';
|
|
20
15
|
}>, ctx: HandlerContext, reqId?: string): Promise<Response>;
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
/** Core command handlers for push, pull, acknowledgement, and failure. */
|
|
2
1
|
import * as resp from '../../../domain/types/response';
|
|
2
|
+
import { validateGroupPullOptions } from '../../../domain/types/group';
|
|
3
3
|
import { jobId, normalizeLegacyJobPayload } from '../../../domain/types/job';
|
|
4
4
|
import { tcpLog } from '../../../shared/logger';
|
|
5
5
|
import { sanitizeServerError, serverErrorDiagnostics } from '../errors';
|
|
6
|
-
import { validateQueueName, validateJobData, validateJobOptions, validateNumericField, } from '../protocol';
|
|
6
|
+
import { validateQueueName, validateGroupId, validateJobData, validateJobOptions, validateNumericField, } from '../protocol';
|
|
7
7
|
import { validatePushBatchJobs, validatePushDependencies } from './pushBatchValidation';
|
|
8
|
-
/** Handle PUSH command */
|
|
9
8
|
export async function handlePush(cmd, ctx, reqId) {
|
|
10
9
|
const queueError = validateQueueName(cmd.queue);
|
|
11
10
|
if (queueError)
|
|
@@ -13,7 +12,9 @@ export async function handlePush(cmd, ctx, reqId) {
|
|
|
13
12
|
const dataError = validateJobData(cmd.data);
|
|
14
13
|
if (dataError)
|
|
15
14
|
return resp.error(dataError, reqId);
|
|
16
|
-
|
|
15
|
+
const groupError = validateGroupId(cmd.groupId);
|
|
16
|
+
if (groupError)
|
|
17
|
+
return resp.error(groupError, reqId);
|
|
17
18
|
const optionsError = validateJobOptions({
|
|
18
19
|
priority: cmd.priority,
|
|
19
20
|
delay: cmd.delay,
|
|
@@ -69,7 +70,6 @@ export async function handlePush(cmd, ctx, reqId) {
|
|
|
69
70
|
return resp.error(sanitizeServerError(err), reqId);
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
|
-
/** Handle PUSHB (batch push) command */
|
|
73
73
|
export async function handlePushBatch(cmd, ctx, reqId) {
|
|
74
74
|
const queueError = validateQueueName(cmd.queue);
|
|
75
75
|
if (queueError)
|
|
@@ -91,48 +91,45 @@ export async function handlePushBatch(cmd, ctx, reqId) {
|
|
|
91
91
|
return resp.error(sanitizeServerError(error), reqId);
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
|
-
/** Handle PULL command */
|
|
95
94
|
export async function handlePull(cmd, ctx, reqId) {
|
|
96
95
|
const queueError = validateQueueName(cmd.queue);
|
|
97
96
|
if (queueError)
|
|
98
97
|
return resp.error(queueError, reqId);
|
|
99
|
-
// Validate timeout
|
|
100
98
|
const timeoutError = validateNumericField(cmd.timeout, 'timeout', { min: 0, max: 60000 });
|
|
101
99
|
if (timeoutError)
|
|
102
100
|
return resp.error(timeoutError, reqId);
|
|
103
|
-
|
|
101
|
+
const groupError = validateGroupPullOptions(cmd.group);
|
|
102
|
+
if (groupError)
|
|
103
|
+
return resp.error(groupError, reqId);
|
|
104
104
|
if (cmd.owner) {
|
|
105
|
-
const { job, token } = await ctx.queueManager.pullWithLock(cmd.queue, cmd.owner, cmd.timeout, cmd.lockTtl, ctx.signal);
|
|
106
|
-
// Register job with client for connection-based release
|
|
105
|
+
const { job, token } = await ctx.queueManager.pullWithLock(cmd.queue, cmd.owner, cmd.timeout, cmd.lockTtl, ctx.signal, cmd.group);
|
|
107
106
|
if (job && ctx.clientId) {
|
|
108
107
|
ctx.queueManager.registerClientJob(ctx.clientId, job.id);
|
|
109
108
|
}
|
|
110
109
|
return resp.pulledJob(job, token, reqId);
|
|
111
110
|
}
|
|
112
111
|
// Standard pull (no lock, but still track for client release unless detached)
|
|
113
|
-
const job = await ctx.queueManager.pull(cmd.queue, cmd.timeout, ctx.signal);
|
|
112
|
+
const job = await ctx.queueManager.pull(cmd.queue, cmd.timeout, ctx.signal, cmd.group);
|
|
114
113
|
if (job && ctx.clientId && !cmd.detach) {
|
|
115
114
|
ctx.queueManager.registerClientJob(ctx.clientId, job.id);
|
|
116
115
|
}
|
|
117
116
|
return resp.nullableJob(job, reqId);
|
|
118
117
|
}
|
|
119
|
-
/** Handle PULLB (batch pull) command - uses optimized single-lock batch pull */
|
|
120
118
|
export async function handlePullBatch(cmd, ctx, reqId) {
|
|
121
119
|
const queueError = validateQueueName(cmd.queue);
|
|
122
120
|
if (queueError)
|
|
123
121
|
return resp.error(queueError, reqId);
|
|
124
|
-
// Validate count
|
|
125
122
|
const countError = validateNumericField(cmd.count, 'count', { min: 1, max: 1000 });
|
|
126
123
|
if (countError)
|
|
127
124
|
return resp.error(countError, reqId);
|
|
128
|
-
// Validate timeout (same bound as PULL)
|
|
129
125
|
const timeoutError = validateNumericField(cmd.timeout, 'timeout', { min: 0, max: 60000 });
|
|
130
126
|
if (timeoutError)
|
|
131
127
|
return resp.error(timeoutError, reqId);
|
|
132
|
-
|
|
128
|
+
const groupError = validateGroupPullOptions(cmd.group);
|
|
129
|
+
if (groupError)
|
|
130
|
+
return resp.error(groupError, reqId);
|
|
133
131
|
if (cmd.owner) {
|
|
134
|
-
const { jobs, tokens } = await ctx.queueManager.pullBatchWithLock(cmd.queue, cmd.count, cmd.owner, cmd.timeout ?? 0, cmd.lockTtl, ctx.signal);
|
|
135
|
-
// Register all jobs with client for connection-based release
|
|
132
|
+
const { jobs, tokens } = await ctx.queueManager.pullBatchWithLock(cmd.queue, cmd.count, cmd.owner, cmd.timeout ?? 0, cmd.lockTtl, ctx.signal, cmd.group);
|
|
136
133
|
if (ctx.clientId) {
|
|
137
134
|
for (const job of jobs) {
|
|
138
135
|
ctx.queueManager.registerClientJob(ctx.clientId, job.id);
|
|
@@ -142,7 +139,7 @@ export async function handlePullBatch(cmd, ctx, reqId) {
|
|
|
142
139
|
}
|
|
143
140
|
// Standard pull (no locks, but still track for client release) — the
|
|
144
141
|
// non-owner branch honors cmd.timeout exactly like the owner branch and PULL.
|
|
145
|
-
const jobs = await ctx.queueManager.pullBatch(cmd.queue, cmd.count, cmd.timeout ?? 0, ctx.signal);
|
|
142
|
+
const jobs = await ctx.queueManager.pullBatch(cmd.queue, cmd.count, cmd.timeout ?? 0, ctx.signal, cmd.group);
|
|
146
143
|
if (ctx.clientId) {
|
|
147
144
|
for (const job of jobs) {
|
|
148
145
|
ctx.queueManager.registerClientJob(ctx.clientId, job.id);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Command } from '../../../domain/types/command';
|
|
2
|
+
import type { Response } from '../../../domain/types/response';
|
|
3
|
+
import type { HandlerContext } from '../types';
|
|
4
|
+
type GroupCommand = Extract<Command, {
|
|
5
|
+
groupId: string;
|
|
6
|
+
}>;
|
|
7
|
+
export declare function handleGroupCommand(command: GroupCommand, context: HandlerContext, requestId?: string): Promise<Response>;
|
|
8
|
+
export declare function handleGroupsJobsCount(command: Extract<Command, {
|
|
9
|
+
cmd: 'GetGroupsJobsCount';
|
|
10
|
+
}>, context: HandlerContext, requestId?: string): Promise<Response>;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { validatePositiveSafeInteger } from '../../../domain/types/group';
|
|
2
|
+
import * as resp from '../../../domain/types/response';
|
|
3
|
+
import { validateGroupId, validateQueueName } from '../protocol';
|
|
4
|
+
function validate(command) {
|
|
5
|
+
const queueError = validateQueueName(command.queue);
|
|
6
|
+
if (queueError)
|
|
7
|
+
return queueError;
|
|
8
|
+
return validateGroupId(command.groupId, true);
|
|
9
|
+
}
|
|
10
|
+
export async function handleGroupCommand(command, context, requestId) {
|
|
11
|
+
const error = validate(command);
|
|
12
|
+
if (error)
|
|
13
|
+
return resp.error(error, requestId);
|
|
14
|
+
const manager = context.queueManager;
|
|
15
|
+
switch (command.cmd) {
|
|
16
|
+
case 'GetGroupJobsCount':
|
|
17
|
+
return resp.data({ count: await manager.getGroupJobsCount(command.queue, command.groupId) }, requestId);
|
|
18
|
+
case 'GetGroupActiveCount':
|
|
19
|
+
return resp.data({ count: await manager.getGroupActiveCount(command.queue, command.groupId) }, requestId);
|
|
20
|
+
case 'SetGroupRateLimit': {
|
|
21
|
+
const maxError = validatePositiveSafeInteger(command.max, 'max');
|
|
22
|
+
const durationError = validatePositiveSafeInteger(command.duration, 'duration');
|
|
23
|
+
const numericError = maxError ?? durationError;
|
|
24
|
+
if (numericError)
|
|
25
|
+
return resp.error(numericError, requestId);
|
|
26
|
+
await manager.setGroupRateLimit(command.queue, command.groupId, command.max, command.duration);
|
|
27
|
+
return resp.ok(undefined, requestId);
|
|
28
|
+
}
|
|
29
|
+
case 'GetGroupRateLimit':
|
|
30
|
+
return resp.data({ limit: await manager.getGroupRateLimit(command.queue, command.groupId) }, requestId);
|
|
31
|
+
case 'RemoveGroupRateLimit':
|
|
32
|
+
return resp.data({ removed: await manager.removeGroupRateLimit(command.queue, command.groupId) }, requestId);
|
|
33
|
+
case 'GetGroupRateLimitTtl':
|
|
34
|
+
return resp.data({
|
|
35
|
+
ttl: await manager.getGroupRateLimitTtl(command.queue, command.groupId, command.maxJobs),
|
|
36
|
+
}, requestId);
|
|
37
|
+
case 'SetGroupConcurrency': {
|
|
38
|
+
const concurrencyError = validatePositiveSafeInteger(command.concurrency, 'concurrency');
|
|
39
|
+
if (concurrencyError)
|
|
40
|
+
return resp.error(concurrencyError, requestId);
|
|
41
|
+
await manager.setGroupConcurrency(command.queue, command.groupId, command.concurrency);
|
|
42
|
+
return resp.ok(undefined, requestId);
|
|
43
|
+
}
|
|
44
|
+
case 'GetGroupConcurrency':
|
|
45
|
+
return resp.data({ concurrency: await manager.getGroupConcurrency(command.queue, command.groupId) }, requestId);
|
|
46
|
+
case 'RemoveGroupConcurrency':
|
|
47
|
+
return resp.data({ removed: await manager.removeGroupConcurrency(command.queue, command.groupId) }, requestId);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
export async function handleGroupsJobsCount(command, context, requestId) {
|
|
51
|
+
const queueError = validateQueueName(command.queue);
|
|
52
|
+
if (queueError)
|
|
53
|
+
return resp.error(queueError, requestId);
|
|
54
|
+
return resp.data({ count: await context.queueManager.getGroupsJobsCount(command.queue) }, requestId);
|
|
55
|
+
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* existence gate handlePush enforces (core.ts).
|
|
6
6
|
*/
|
|
7
7
|
import { jobId, normalizeLegacyJobPayload, } from '../../../domain/types/job';
|
|
8
|
-
import { validateJobData, validateJobOptions } from '../protocol';
|
|
8
|
+
import { validateGroupId, validateJobData, validateJobOptions } from '../protocol';
|
|
9
9
|
function dependencyExistsLocally(id, ctx) {
|
|
10
10
|
return (ctx.queueManager.getJobIndex().has(id) ||
|
|
11
11
|
ctx.queueManager.getCompletedJobs().has(id) ||
|
|
@@ -88,6 +88,9 @@ function validateJobs(jobs, state) {
|
|
|
88
88
|
const dataError = validateJobData(job.data);
|
|
89
89
|
if (dataError)
|
|
90
90
|
return `jobs[${i}]: ${dataError}`;
|
|
91
|
+
const groupError = validateGroupId(job.groupId);
|
|
92
|
+
if (groupError)
|
|
93
|
+
return `jobs[${i}]: ${groupError}`;
|
|
91
94
|
const optionsError = validateJobOptions({
|
|
92
95
|
priority: job.priority,
|
|
93
96
|
delay: job.delay,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export declare function validateQueueName(name: string): string | null;
|
|
2
|
+
export { validateGroupId } from '../../../domain/types/group';
|
|
2
3
|
export declare function validateJobData(data: unknown): string | null;
|
|
3
4
|
export declare function validateNumericField(value: unknown, name: string, options?: {
|
|
4
5
|
min?: number;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { createConnectionState, errorResponse, parseCommand, parseCommands, serializeResponse, } from './protocol/commands';
|
|
2
2
|
export { FrameParser, FrameSizeError, MAX_FRAME_SIZE } from './protocol/frameParser';
|
|
3
3
|
export { LineBuffer } from './protocol/lineBuffer';
|
|
4
|
-
export { validateBackoffField, validateJobData, validateJobOptions, validateNumericField, validateQueueName, } from './protocol/validation';
|
|
4
|
+
export { validateBackoffField, validateGroupId, validateJobData, validateJobOptions, validateNumericField, validateQueueName, } from './protocol/validation';
|
|
5
5
|
export type { ConnectionState } from './types/protocol';
|
|
6
6
|
export { validateWebhookUrl } from '../../shared/webhookValidation';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { createConnectionState, errorResponse, parseCommand, parseCommands, serializeResponse, } from './protocol/commands';
|
|
2
2
|
export { FrameParser, FrameSizeError, MAX_FRAME_SIZE } from './protocol/frameParser';
|
|
3
3
|
export { LineBuffer } from './protocol/lineBuffer';
|
|
4
|
-
export { validateBackoffField, validateJobData, validateJobOptions, validateNumericField, validateQueueName, } from './protocol/validation';
|
|
4
|
+
export { validateBackoffField, validateGroupId, validateJobData, validateJobOptions, validateNumericField, validateQueueName, } from './protocol/validation';
|
|
5
5
|
export { validateWebhookUrl } from '../../shared/webhookValidation';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bunqueue",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.2",
|
|
4
4
|
"description": "High-performance job queue for Bun and AI agents. Memory or one-file SQLite, optional PostgreSQL 15–18 multi-broker persistence, cron, retries, DLQ, and MCP.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agentic",
|
|
@@ -127,6 +127,7 @@
|
|
|
127
127
|
"bench:autobatch": "bun run bench/local-autobatch.ts",
|
|
128
128
|
"bench:postgres:versions": "bun run bench/postgres-versions.ts",
|
|
129
129
|
"bench:pushbulk": "bun run bench/pushbulk-delta.ts",
|
|
130
|
+
"bench:sqlite-lifecycle": "bun run bench/sqlite-lifecycle-batching.ts",
|
|
130
131
|
"bench:workflow": "bun run bench/workflow-engine.ts",
|
|
131
132
|
"bench:workflow:scale": "bun run bench/workflow-engine/scale.ts",
|
|
132
133
|
"bench:joblist": "bun run bench/job-list-perf.ts",
|