lonnymq 1.0.2 → 1.2.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/index.cjs DELETED
@@ -1,666 +0,0 @@
1
- var{defineProperty:T,getOwnPropertyNames:H,getOwnPropertyDescriptor:w}=Object,k=Object.prototype.hasOwnProperty;var I=new WeakMap,P=(e)=>{var t=I.get(e),a;if(t)return t;if(t=T({},"__esModule",{value:!0}),e&&typeof e==="object"||typeof e==="function")H(e).map((E)=>!k.call(t,E)&&T(t,E,{get:()=>e[E],enumerable:!(a=w(e,E))||a.enumerable}));return I.set(e,t),t};var Q=(e,t)=>{for(var a in t)T(e,a,{get:t[a],enumerable:!0,configurable:!0,set:(E)=>t[a]=()=>E})};var re={};Q(re,{Queue:()=>D,MessageHeartbeatCommand:()=>m,MessageDequeueCommand:()=>o,MessageDeleteCommand:()=>i,MessageDeferCommand:()=>d,MessageCreateCommand:()=>l,ChannelPolicySetCommand:()=>u,ChannelPolicyClearCommand:()=>c});module.exports=P(re);var r=(e)=>({nodeType:"VALUE",value:e}),s=(e)=>({nodeType:"REF",value:e}),z=(e)=>({nodeType:"RAW",value:e}),V=(e)=>{return`'${e.replace(/'/g,"''")}'`},W=(e)=>{if(e===null)return"NULL";else if(typeof e==="string")return V(e);else if(typeof e==="number")return e.toString();else if(typeof e==="boolean")return e?"TRUE":"FALSE";else if(e instanceof Date)return`'${e.toISOString()}'`;else if(typeof e==="bigint")return e.toString();else throw Error(`Unsupported value type: ${typeof e}`)},Y=(e)=>{return`"${e.replace(/"/g,'""')}"`},X=(e)=>{if(e.nodeType==="VALUE")return W(e.value);else if(e.nodeType==="REF")return Y(e.value);else if(e.nodeType==="RAW")return e.value;else throw Error("Unsupported SQL node type")};var n=(e,...t)=>{let a=[];for(let E=0;E<e.length;E+=1)if(a.push(e[E]),E<t.length)a.push(X(t[E]));return z(a.join(""))};class c{schema;channelId;createdAt;constructor(e){this.schema=e.schema,this.channelId=e.channelId,this.createdAt=new Date}async execute(e){await e.query(n`
2
- SELECT 1 FROM ${s(this.schema)}."channel_policy_clear"(
3
- $1
4
- )
5
- `.value,[this.channelId])}}class u{schema;channelId;maxConcurrency;maxSize;releaseIntervalMs;createdAt;constructor(e){this.schema=e.schema,this.channelId=e.channelId;let t=e.maxConcurrency??null;this.maxConcurrency=t!==null?Math.max(1,t):null;let a=e.maxSize??null;this.maxSize=a!==null?Math.max(1,a):null;let E=e.releaseIntervalMs??null;this.releaseIntervalMs=E!==null?Math.max(0,E):null,this.createdAt=new Date}async execute(e){await e.query(n`
6
- SELECT 1 FROM ${s(this.schema)}."channel_policy_set"(
7
- $1,
8
- $2::INTEGER,
9
- $3::INTEGER,
10
- $4::INTEGER
11
- )
12
- `.value,[this.channelId,this.maxConcurrency,this.maxSize,this.releaseIntervalMs])}}class l{schema;channelId;content;dequeueAt;constructor(e){this.schema=e.schema,this.channelId=e.channelId,this.content=e.content,this.dequeueAt=e.dequeueAt}async execute(e){let t=await e.query(n`
13
- SELECT
14
- result_code,
15
- metadata
16
- FROM ${s(this.schema)}."message_create"(
17
- $1,
18
- $2,
19
- $3::BIGINT
20
- )
21
- `.value,[this.channelId,this.content,this.dequeueAt]).then((a)=>a.rows[0]);if(t.result_code===0)return{resultType:"MESSAGE_CREATED",id:BigInt(t.metadata.id),channelSize:t.metadata.channel_size};else if(t.result_code===1)return{resultType:"MESSAGE_DROPPED"};else throw Error("Unexpected result code")}}class o{schema;lockMs;constructor(e){this.schema=e.schema,this.lockMs=e.lockMs}async execute(e){let t=await e.query(n`
22
- SELECT
23
- result_code,
24
- metadata,
25
- content,
26
- state
27
- FROM ${s(this.schema)}."message_dequeue"($1::BIGINT)
28
- `.value,[this.lockMs]).then((a)=>a.rows[0]);if(t.result_code===0)return{resultType:"MESSAGE_NOT_AVAILABLE"};else if(t.result_code===1)return{resultType:"MESSAGE_DEQUEUED",id:BigInt(t.metadata.id),channelId:t.metadata.channel_id,isUnlocked:t.metadata.is_unlocked,content:t.content,state:t.state,numAttempts:t.metadata.num_attempts};else throw Error("Unexpected dequeue result")}}class i{schema;id;numAttempts;constructor(e){this.schema=e.schema,this.id=e.id,this.numAttempts=e.numAttempts}async execute(e){let t=await e.query(n`
29
- SELECT * FROM ${s(this.schema)}."message_delete"(
30
- $1::BIGINT,
31
- $2::BIGINT
32
- )
33
- `.value,[this.id.toString(),this.numAttempts]).then((a)=>a.rows[0]);if(t.result_code===0)return{resultType:"MESSAGE_NOT_FOUND"};else if(t.result_code===1)return{resultType:"STATE_INVALID"};else if(t.result_code===2)return{resultType:"MESSAGE_DELETED"};else throw Error("Unexpected result")}}class d{schema;id;numAttempts;state;dequeueAt;constructor(e){this.schema=e.schema,this.numAttempts=e.numAttempts,this.id=e.id,this.state=e.state,this.dequeueAt=e.dequeueAt}async execute(e){let t=await e.query(n`
34
- SELECT * FROM ${s(this.schema)}."message_defer"(
35
- $1::BIGINT,
36
- $2::BIGINT,
37
- $3::BIGINT,
38
- $4
39
- )
40
- `.value,[this.id.toString(),this.numAttempts,this.dequeueAt,this.state]).then((a)=>a.rows[0]);if(t.result_code===0)return{resultType:"MESSAGE_NOT_FOUND"};else if(t.result_code===1)return{resultType:"STATE_INVALID"};else if(t.result_code===2)return{resultType:"MESSAGE_DEFERRED"};else throw Error("Unexpected result")}}class m{schema;id;numAttempts;lockMs;constructor(e){this.schema=e.schema,this.numAttempts=e.numAttempts,this.id=e.id,this.lockMs=e.lockMs}async execute(e){let t=await e.query(n`
41
- SELECT * FROM ${s(this.schema)}."message_heartbeat"(
42
- $1::BIGINT,
43
- $2::BIGINT,
44
- $3::BIGINT
45
- )
46
- `.value,[this.id.toString(),this.numAttempts,this.lockMs]).then((a)=>a.rows[0]);if(t.result_code===0)return{resultType:"MESSAGE_NOT_FOUND"};else if(t.result_code===1)return{resultType:"MESSAGE_STATE_INVALID"};else if(t.result_code===2)return{resultType:"MESSAGE_HEARTBEATED"};else throw Error("Unexpected result")}}var y=(e)=>{let t=e.split(`
47
- `),a=Number.MAX_SAFE_INTEGER;for(let E of t){if(E.trim().length===0)continue;let B=E.search(/\S/);a=Math.min(a,B)}return t.map((E)=>E.slice(a)).join(`
48
- `).trim()};var h=require("path"),__filename="/home/runner/work/lonnymq/lonnymq/src/core/path.ts",te=h.dirname(h.dirname(__filename)),se=new RegExp(`^${te}/`),_=(e)=>{return e.replace(se,"")};var __filename="/home/runner/work/lonnymq/lonnymq/src/install/table-channel-policy.ts",v={name:_(__filename),sql:(e)=>{return[n`
49
- CREATE TABLE ${s(e.schema)}."channel_policy" (
50
- "id" TEXT NOT NULL,
51
- "max_concurrency" INTEGER,
52
- "max_size" INTEGER,
53
- "release_interval_ms" INTEGER,
54
- PRIMARY KEY ("id")
55
- );
56
- `]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/install/table-channel-state.ts",M={name:_(__filename),sql:(e)=>{let t=[e.schema,"channel_state_dequeue_ix"].join("_");return[n`
57
- CREATE TABLE ${s(e.schema)}."channel_state" (
58
- "id" TEXT NOT NULL,
59
- "max_concurrency" INTEGER,
60
- "max_size" INTEGER,
61
- "release_interval_ms" INTEGER,
62
- "current_size" INTEGER NOT NULL,
63
- "current_concurrency" INTEGER NOT NULL,
64
- "message_id" BIGINT,
65
- "message_dequeue_at" BIGINT,
66
- "dequeue_prev_at" BIGINT NOT NULL,
67
- "dequeue_next_at" BIGINT NULL,
68
- PRIMARY KEY ("id")
69
- );
70
- `,n`
71
- CREATE INDEX ${s(t)}
72
- ON ${s(e.schema)}."channel_state" (
73
- "dequeue_next_at" ASC
74
- ) WHERE "message_id" IS NOT NULL
75
- AND ("max_concurrency" IS NULL OR "current_concurrency" < "max_concurrency");
76
- `]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/install/table-message.ts",C={name:_(__filename),sql:(e)=>{return[n`
77
- CREATE TABLE ${s(e.schema)}."message" (
78
- "id" BIGSERIAL NOT NULL,
79
- "channel_id" TEXT NOT NULL,
80
- "content" BYTEA NOT NULL,
81
- "state" BYTEA,
82
- "is_locked" BOOLEAN NOT NULL,
83
- "num_attempts" BIGINT NOT NULL,
84
- "dequeue_at" BIGINT NOT NULL,
85
- "unlock_at" BIGINT,
86
- PRIMARY KEY ("id")
87
- );
88
- `,n`
89
- CREATE INDEX "message_dequeue_ix"
90
- ON ${s(e.schema)}."message" (
91
- "channel_id",
92
- "dequeue_at" ASC,
93
- "id" ASC
94
- ) WHERE NOT "is_locked";
95
- `,n`
96
- CREATE INDEX "message_locked_dequeue_ix"
97
- ON ${s(e.schema)}."message" (
98
- "unlock_at" ASC
99
- ) WHERE "is_locked";
100
- `]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/install/function-message-create.ts",L={name:_(__filename),sql:(e)=>{return[n`
101
- CREATE FUNCTION ${s(e.schema)}."message_create" (
102
- p_channel TEXT,
103
- p_content BYTEA,
104
- p_dequeue_at BIGINT
105
- ) RETURNS TABLE (
106
- result_code INTEGER,
107
- metadata JSON
108
- ) AS $$
109
- DECLARE
110
- v_now BIGINT;
111
- v_dequeue_at BIGINT;
112
- v_channel_policy RECORD;
113
- v_channel_state RECORD;
114
- v_message RECORD;
115
- BEGIN
116
- v_now := ${s(e.schema)}."epoch"();
117
- v_dequeue_at := COALESCE(p_dequeue_at, v_now);
118
-
119
- SELECT
120
- "id",
121
- "current_concurrency",
122
- "current_size",
123
- "max_concurrency",
124
- "max_size",
125
- "release_interval_ms",
126
- "dequeue_prev_at",
127
- "message_id",
128
- "message_dequeue_at"
129
- FROM ${s(e.schema)}."channel_state"
130
- WHERE "id" = p_channel
131
- FOR UPDATE
132
- INTO v_channel_state;
133
-
134
- IF v_channel_state."id" IS NULL THEN
135
- SELECT
136
- "channel_policy"."max_concurrency",
137
- "channel_policy"."max_size",
138
- "channel_policy"."release_interval_ms"
139
- FROM ${s(e.schema)}."channel_policy"
140
- WHERE "id" = p_channel
141
- FOR SHARE
142
- INTO v_channel_policy;
143
-
144
- INSERT INTO ${s(e.schema)}."channel_state" (
145
- "id",
146
- "current_concurrency",
147
- "current_size",
148
- "max_concurrency",
149
- "max_size",
150
- "release_interval_ms",
151
- "dequeue_prev_at"
152
- ) VALUES (
153
- p_channel,
154
- 0,
155
- 0,
156
- v_channel_policy."max_concurrency",
157
- v_channel_policy."max_size",
158
- v_channel_policy."release_interval_ms",
159
- v_now
160
- ) RETURNING
161
- "id",
162
- "current_concurrency",
163
- "current_size",
164
- "max_concurrency",
165
- "max_size",
166
- "release_interval_ms",
167
- "dequeue_prev_at",
168
- "message_id",
169
- "message_dequeue_at"
170
- INTO v_channel_state;
171
- END IF;
172
-
173
- IF v_channel_state."current_size" >= v_channel_state."max_size" THEN
174
- RETURN QUERY SELECT
175
- ${r(1)},
176
- NULL::JSON;
177
- RETURN;
178
- END IF;
179
-
180
- INSERT INTO ${s(e.schema)}."message" (
181
- "channel_id",
182
- "content",
183
- "is_locked",
184
- "num_attempts",
185
- "dequeue_at"
186
- ) VALUES (
187
- p_channel,
188
- p_content,
189
- FALSE,
190
- 0,
191
- v_dequeue_at
192
- ) RETURNING
193
- "id"
194
- INTO v_message;
195
-
196
- IF
197
- v_channel_state."message_id" IS NULL OR
198
- v_dequeue_at < v_channel_state."message_dequeue_at" OR
199
- v_dequeue_at = v_channel_state."message_dequeue_at" AND v_message."id" < v_channel_state."message_id"
200
- THEN
201
- UPDATE ${s(e.schema)}."channel_state" SET
202
- "current_size" = v_channel_state."current_size" + 1,
203
- "message_id" = v_message."id",
204
- "message_dequeue_at" = v_dequeue_at,
205
- "dequeue_next_at" = GREATEST(
206
- v_channel_state."dequeue_prev_at" + COALESCE(v_channel_state."release_interval_ms", 0),
207
- v_dequeue_at
208
- )
209
- WHERE "id" = v_channel_state."id";
210
- ELSE
211
- UPDATE ${s(e.schema)}."channel_state" SET
212
- "current_size" = v_channel_state."current_size" + 1
213
- WHERE "id" = v_channel_state."id";
214
- END IF;
215
-
216
- IF ${r(e.eventChannel!==null)} THEN
217
- PERFORM PG_NOTIFY(
218
- ${r(e.eventChannel)},
219
- JSON_BUILD_OBJECT(
220
- 'type', ${r(0)},
221
- 'id', v_message."id"::TEXT,
222
- 'dequeue_at', v_dequeue_at
223
- )::TEXT
224
- );
225
- END IF;
226
-
227
- RETURN QUERY SELECT
228
- ${r(0)},
229
- JSON_BUILD_OBJECT(
230
- 'id', v_message."id"::TEXT,
231
- 'channel_size', v_channel_state."current_size" + 1
232
- );
233
- END;
234
- $$ LANGUAGE plpgsql;
235
- `]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/install/function-message-dequeue.ts",ne=(e)=>n`
236
- SELECT
237
- "message"."id",
238
- "message"."state",
239
- "message"."content",
240
- "message"."channel_id",
241
- "message"."unlock_at",
242
- "message"."num_attempts"
243
- FROM ${s(e.schema)}."message"
244
- WHERE "is_locked"
245
- AND "unlock_at" <= ${e.now}
246
- ORDER BY "unlock_at" ASC
247
- `,ae=(e)=>n`
248
- SELECT
249
- "channel_state"."id",
250
- "channel_state"."release_interval_ms",
251
- "channel_state"."message_id",
252
- "channel_state"."dequeue_next_at",
253
- "channel_state"."dequeue_prev_at",
254
- "channel_state"."current_concurrency"
255
- FROM ${s(e.schema)}."channel_state"
256
- WHERE "message_id" IS NOT NULL
257
- AND ("max_concurrency" IS NULL OR "current_concurrency" < "max_concurrency")
258
- ORDER BY "dequeue_next_at" ASC
259
- `,Ee=(e)=>n`
260
- SELECT
261
- "message"."id",
262
- "message"."dequeue_at"
263
- FROM ${s(e.schema)}."message"
264
- WHERE NOT "is_locked"
265
- AND "channel_id" = ${e.channelId}
266
- ORDER BY "dequeue_at" ASC, "id" ASC
267
- `,O={name:_(__filename),sql:(e)=>{let t=ne({now:n`v_now`,schema:e.schema}),a=Ee({channelId:n`v_channel_state."id"`,schema:e.schema}),E=ae({schema:e.schema});return[n`
268
- CREATE FUNCTION ${s(e.schema)}."message_dequeue" (
269
- p_lock_ms BIGINT
270
- )
271
- RETURNS TABLE (
272
- result_code INTEGER,
273
- content BYTEA,
274
- state BYTEA,
275
- metadata JSON
276
- ) AS $$
277
- DECLARE
278
- v_now BIGINT;
279
- v_channel_state RECORD;
280
- v_message_locked RECORD;
281
- v_message_dequeue RECORD;
282
- v_message_next RECORD;
283
- BEGIN
284
- v_now := ${s(e.schema)}."epoch"();
285
-
286
- ${t}
287
- FOR UPDATE
288
- SKIP LOCKED
289
- LIMIT 1
290
- INTO v_message_locked;
291
-
292
- IF v_message_locked."id" IS NOT NULL THEN
293
- UPDATE ${s(e.schema)}."message" SET
294
- "num_attempts" = v_message_locked."num_attempts" + 1,
295
- "unlock_at" = v_now + p_lock_ms
296
- WHERE "id" = v_message_locked."id";
297
-
298
- RETURN QUERY SELECT
299
- ${r(1)},
300
- v_message_locked.content,
301
- v_message_locked.state,
302
- JSON_BUILD_OBJECT(
303
- 'id', v_message_locked."id",
304
- 'is_unlocked', TRUE,
305
- 'channel', v_message_locked."channel_id",
306
- 'num_attempts', v_message_locked."num_attempts" + 1
307
- );
308
- RETURN;
309
- END IF;
310
-
311
- ${E}
312
- FOR UPDATE
313
- SKIP LOCKED
314
- LIMIT 1
315
- INTO v_channel_state;
316
-
317
- IF v_channel_state."id" IS NULL OR v_channel_state."dequeue_next_at" > v_now THEN
318
- RETURN QUERY SELECT
319
- ${r(0)},
320
- NULL::BYTEA,
321
- NULL::BYTEA,
322
- NULL::JSON;
323
- RETURN;
324
- END IF;
325
-
326
- SELECT
327
- "message"."id",
328
- "message"."channel_id",
329
- "message"."content",
330
- "message"."num_attempts",
331
- "message"."state"
332
- FROM ${s(e.schema)}."message"
333
- WHERE "id" = v_channel_state."message_id"
334
- INTO v_message_dequeue;
335
-
336
- UPDATE ${s(e.schema)}."message" SET
337
- "is_locked" = TRUE,
338
- "num_attempts" = v_message_dequeue."num_attempts" + 1,
339
- "unlock_at" = v_now + p_lock_ms
340
- WHERE "id" = v_message_dequeue."id";
341
-
342
- ${a}
343
- LIMIT 1
344
- INTO v_message_next;
345
-
346
- IF v_message_next."id" IS NULL THEN
347
- UPDATE ${s(e.schema)}."channel_state" SET
348
- "current_concurrency" = v_channel_state."current_concurrency" + 1,
349
- "dequeue_prev_at" = v_now,
350
- "message_id" = NULL
351
- WHERE "id" = v_channel_state."id";
352
- ELSE
353
- UPDATE ${s(e.schema)}."channel_state" SET
354
- "current_concurrency" = v_channel_state."current_concurrency" + 1,
355
- "message_id" = v_message_next."id",
356
- "message_dequeue_at" = v_message_next."dequeue_at",
357
- "dequeue_prev_at" = v_now,
358
- "dequeue_next_at" = GREATEST(
359
- v_message_next."dequeue_at",
360
- v_now + COALESCE(v_channel_state."release_interval_ms", 0)
361
- )
362
- WHERE "id" = v_channel_state."id";
363
- END IF;
364
-
365
- RETURN QUERY SELECT
366
- ${r(1)},
367
- v_message_dequeue."content",
368
- v_message_dequeue."state",
369
- JSON_BUILD_OBJECT(
370
- 'id', v_message_dequeue."id"::TEXT,
371
- 'is_unlocked', FALSE,
372
- 'channel_id', v_message_dequeue."channel_id",
373
- 'num_attempts', v_message_dequeue."num_attempts" + 1
374
- );
375
- RETURN;
376
- END;
377
- $$ LANGUAGE plpgsql;
378
- `]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/install/function-message-delete.ts",U={name:_(__filename),sql:(e)=>{return[n`
379
- CREATE FUNCTION ${s(e.schema)}."message_delete" (
380
- p_id BIGINT,
381
- p_num_attempts BIGINT
382
- )
383
- RETURNS TABLE (
384
- result_code INTEGER
385
- ) AS $$
386
- DECLARE
387
- v_channel_policy RECORD;
388
- v_channel_state RECORD;
389
- v_message RECORD;
390
- BEGIN
391
- SELECT
392
- "message"."id",
393
- "message"."channel_id",
394
- "message"."num_attempts",
395
- "message"."is_locked"
396
- FROM ${s(e.schema)}."message"
397
- WHERE "id" = p_id
398
- FOR UPDATE
399
- INTO v_message;
400
-
401
- IF v_message."id" IS NULL THEN
402
- RETURN QUERY SELECT
403
- ${r(0)};
404
- RETURN;
405
- ELSIF NOT v_message."is_locked" OR v_message."num_attempts" <> p_num_attempts THEN
406
- RETURN QUERY SELECT
407
- ${r(1)};
408
- RETURN;
409
- END IF;
410
-
411
- SELECT
412
- "channel_policy"."id"
413
- FROM ${s(e.schema)}."channel_policy"
414
- WHERE "id" = v_message."channel_id"
415
- FOR SHARE
416
- INTO v_channel_policy;
417
-
418
- SELECT
419
- "channel_state"."id",
420
- "channel_state"."current_size",
421
- "channel_state"."current_concurrency"
422
- FROM ${s(e.schema)}."channel_state"
423
- WHERE "id" = v_message."channel_id"
424
- FOR UPDATE
425
- INTO v_channel_state;
426
-
427
- IF v_channel_policy."id" IS NULL AND v_channel_state."current_size" = 1 THEN
428
- DELETE FROM ${s(e.schema)}."channel_state"
429
- WHERE "id" = v_channel_state."id";
430
- ELSE
431
- UPDATE ${s(e.schema)}."channel_state" SET
432
- "current_concurrency" = v_channel_state."current_concurrency" - 1,
433
- "current_size" = v_channel_state."current_size" - 1
434
- WHERE "id" = v_channel_state."id";
435
- END IF;
436
-
437
- IF ${r(e.eventChannel!==null)} THEN
438
- PERFORM PG_NOTIFY(
439
- ${r(e.eventChannel)},
440
- JSON_BUILD_OBJECT(
441
- 'type', ${r(1)},
442
- 'id', p_id::TEXT
443
- )::TEXT
444
- );
445
- END IF;
446
-
447
- DELETE FROM ${s(e.schema)}."message"
448
- WHERE "id" = p_id;
449
-
450
- RETURN QUERY SELECT
451
- ${r(2)};
452
- RETURN;
453
- END;
454
- $$ LANGUAGE plpgsql;
455
- `]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/install/function-message-defer.ts",f={name:_(__filename),sql:(e)=>{return[n`
456
- CREATE FUNCTION ${s(e.schema)}."message_defer" (
457
- p_id BIGINT,
458
- p_num_attempts BIGINT,
459
- p_dequeue_at BIGINT,
460
- p_state BYTEA
461
- )
462
- RETURNS TABLE (
463
- result_code INTEGER
464
- ) AS $$
465
- DECLARE
466
- v_now BIGINT;
467
- v_channel_state RECORD;
468
- v_message RECORD;
469
- v_dequeue_at BIGINT;
470
- BEGIN
471
- v_now := ${s(e.schema)}."epoch"();
472
-
473
- SELECT
474
- "message"."id",
475
- "message"."channel_id",
476
- "message"."num_attempts",
477
- "message"."is_locked"
478
- FROM ${s(e.schema)}."message"
479
- WHERE "id" = p_id
480
- FOR UPDATE
481
- INTO v_message;
482
-
483
- IF v_message."id" IS NULL THEN
484
- RETURN QUERY SELECT
485
- ${r(0)};
486
- RETURN;
487
- ELSIF NOT v_message."is_locked" OR v_message."num_attempts" <> p_num_attempts THEN
488
- RETURN QUERY SELECT
489
- ${r(1)};
490
- RETURN;
491
- END IF;
492
-
493
- SELECT
494
- "channel_state"."current_concurrency",
495
- "channel_state"."release_interval_ms",
496
- "channel_state"."message_id",
497
- "channel_state"."message_dequeue_at",
498
- "channel_state"."dequeue_prev_at"
499
- FROM ${s(e.schema)}."channel_state"
500
- WHERE "id" = v_message."channel_id"
501
- FOR UPDATE
502
- INTO v_channel_state;
503
-
504
- v_dequeue_at := COALESCE(p_dequeue_at, v_now);
505
-
506
- IF
507
- v_channel_state."message_id" IS NULL OR
508
- v_dequeue_at < v_channel_state."message_dequeue_at" OR
509
- v_dequeue_at = v_channel_state."message_dequeue_at" AND v_message."id" < v_channel_state."message_id"
510
- THEN
511
- UPDATE ${s(e.schema)}."channel_state" SET
512
- "current_concurrency" = v_channel_state."current_concurrency" - 1,
513
- "message_id" = v_message."id",
514
- "message_dequeue_at" = v_dequeue_at,
515
- "dequeue_next_at" = GREATEST(
516
- v_channel_state."dequeue_prev_at" + COALESCE(v_channel_state."release_interval_ms", 0),
517
- v_dequeue_at
518
- )
519
- WHERE "id" = v_message."channel_id";
520
- ELSE
521
- UPDATE ${s(e.schema)}."channel_state" SET
522
- "current_concurrency" = v_channel_state."current_concurrency" - 1
523
- WHERE "id" = v_message."channel_id";
524
- END IF;
525
-
526
- UPDATE ${s(e.schema)}."message" SET
527
- "state" = p_state,
528
- "is_locked" = FALSE,
529
- "dequeue_at" = v_dequeue_at
530
- WHERE "id" = p_id;
531
-
532
- IF ${r(e.eventChannel!==null)} THEN
533
- PERFORM PG_NOTIFY(
534
- ${r(e.eventChannel)},
535
- JSON_BUILD_OBJECT(
536
- 'type', ${r(2)},
537
- 'dequeue_at', v_dequeue_at,
538
- 'id', p_id::TEXT
539
- )::TEXT
540
- );
541
- END IF;
542
-
543
- RETURN QUERY SELECT
544
- ${r(2)};
545
- RETURN;
546
- END;
547
- $$ LANGUAGE plpgsql;
548
- `]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/install/function-channel-policy-clear.ts",G={name:_(__filename),sql:(e)=>{return[n`
549
- CREATE FUNCTION ${s(e.schema)}."channel_policy_clear" (
550
- p_id TEXT
551
- ) RETURNS VOID AS $$
552
- DECLARE
553
- v_channel_state RECORD;
554
- BEGIN
555
- DELETE FROM ${s(e.schema)}."channel_policy"
556
- WHERE "id" = p_id;
557
-
558
- SELECT
559
- "channel_state"."id",
560
- "channel_state"."current_size"
561
- FROM ${s(e.schema)}."channel_state"
562
- WHERE "id" = p_id
563
- FOR UPDATE
564
- INTO v_channel_state;
565
-
566
- IF v_channel_state."current_size" = 0 THEN
567
- DELETE FROM ${s(e.schema)}."channel_state"
568
- WHERE "id" = v_channel_state."id";
569
- ELSE
570
- UPDATE ${s(e.schema)}."channel_state" SET
571
- "max_concurrency" = NULL,
572
- "release_interval_ms" = NULL
573
- WHERE "id" = p_id;
574
- END IF;
575
- END;
576
- $$ LANGUAGE plpgsql;
577
- `]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/install/function-channel-policy-set.ts",q={name:_(__filename),sql:(e)=>{return[n`
578
- CREATE FUNCTION ${s(e.schema)}."channel_policy_set" (
579
- p_id TEXT,
580
- p_max_concurrency INTEGER,
581
- p_max_size INTEGER,
582
- p_release_interval_ms INTEGER
583
- ) RETURNS VOID AS $$
584
- BEGIN
585
- INSERT INTO ${s(e.schema)}."channel_policy" (
586
- "id",
587
- "max_concurrency",
588
- "max_size",
589
- "release_interval_ms"
590
- ) VALUES (
591
- p_id,
592
- p_max_concurrency,
593
- p_max_size,
594
- p_release_interval_ms
595
- ) ON CONFLICT ("id") DO UPDATE SET
596
- "max_concurrency" = EXCLUDED."max_concurrency",
597
- "max_size" = EXCLUDED."max_size",
598
- "release_interval_ms" = EXCLUDED."release_interval_ms";
599
-
600
- UPDATE ${s(e.schema)}."channel_state" SET
601
- "max_concurrency" = p_max_concurrency,
602
- "max_size" = p_max_size,
603
- "release_interval_ms" = p_release_interval_ms
604
- WHERE "id" = p_id;
605
- END;
606
- $$ LANGUAGE plpgsql;
607
- `]}};class S{schema;channelId;adaptor;constructor(e){this.schema=e.schema,this.adaptor=e.adaptor,this.channelId=e.channelId}async create(e){let t=this.adaptor(e.databaseClient);return await new l({schema:this.schema,channelId:this.channelId,content:e.content,dequeueAt:e.dequeueAt??null}).execute(t)}}class N{schema;adaptor;channelId;constructor(e){this.schema=e.schema,this.adaptor=e.adaptor,this.channelId=e.channelId}set(e){let t=this.adaptor(e.databaseClient);return new u({schema:this.schema,channelId:this.channelId,maxConcurrency:e.maxConcurrency,maxSize:e.maxSize,releaseIntervalMs:e.releaseIntervalMs}).execute(t)}clear(e){let t=this.adaptor(e.databaseClient);return new c({schema:this.schema,channelId:this.channelId}).execute(t)}}class A{policy;message;constructor(e){this.message=new S({schema:e.schema,adaptor:e.adaptor,channelId:e.channelId}),this.policy=new N({schema:e.schema,adaptor:e.adaptor,channelId:e.channelId})}}class p{schema;adaptor;id;isUnlocked;channelId;content;state;numAttempts;constructor(e){this.schema=e.schema,this.adaptor=e.adaptor,this.id=e.id,this.channelId=e.channelId,this.isUnlocked=e.isUnlocked,this.content=e.content,this.state=e.state,this.numAttempts=e.numAttempts}async defer(e){let t=this.adaptor(e.databaseClient);return new d({schema:this.schema,id:this.id,numAttempts:this.numAttempts,dequeueAt:e.dequeueAt??null,state:e.state??null}).execute(t)}async delete(e){let t=this.adaptor(e.databaseClient);return new i({schema:this.schema,numAttempts:this.numAttempts,id:this.id}).execute(t)}async heartbeat(e){let t=this.adaptor(e.databaseClient);return new m({schema:this.schema,id:this.id,numAttempts:this.numAttempts,lockMs:e.lockMs}).execute(t)}}var x=require("crypto");class g{schema;adaptor;constructor(e){this.schema=e.schema,this.adaptor=e.adaptor}async create(e){let t=this.adaptor(e.databaseClient);return await new l({schema:this.schema,content:e.content,dequeueAt:e.dequeueAt??null,channelId:x.randomUUID()}).execute(t)}}var __filename="/home/runner/work/lonnymq/lonnymq/src/install/function-message-heartbeat.ts",$={name:_(__filename),sql:(e)=>{return[n`
608
- CREATE FUNCTION ${s(e.schema)}."message_heartbeat" (
609
- p_id BIGINT,
610
- p_num_attempts BIGINT,
611
- p_lock_ms BIGINT
612
- )
613
- RETURNS TABLE (
614
- result_code INTEGER
615
- ) AS $$
616
- DECLARE
617
- v_now BIGINT;
618
- v_message RECORD;
619
- BEGIN
620
- v_now := ${s(e.schema)}."epoch"();
621
-
622
- SELECT
623
- "message"."id",
624
- "message"."num_attempts",
625
- "message"."is_locked",
626
- "message"."unlock_at"
627
- FROM ${s(e.schema)}."message"
628
- WHERE "id" = p_id
629
- FOR UPDATE
630
- INTO v_message;
631
-
632
- IF v_message."id" IS NULL THEN
633
- RETURN QUERY SELECT
634
- ${r(0)};
635
- RETURN;
636
- ELSIF NOT v_message."is_locked" OR v_message."num_attempts" <> p_num_attempts THEN
637
- RETURN QUERY SELECT
638
- ${r(1)};
639
- RETURN;
640
- END IF;
641
-
642
- UPDATE ${s(e.schema)}."message" SET
643
- "unlock_at" = GREATEST(
644
- v_now + p_lock_ms,
645
- v_message."unlock_at"
646
- )
647
- WHERE "id" = p_id;
648
-
649
- RETURN QUERY SELECT
650
- ${r(2)};
651
- RETURN;
652
- END;
653
- $$ LANGUAGE plpgsql;
654
- `]}};var F=(e)=>{let t=JSON.parse(e);if(t.type===0)return{eventType:"MESSAGE_CREATED",id:t.id,dequeueAt:Number(t.dequeue_at)};else if(t.type===1)return{eventType:"MESSAGE_DELETED",id:t.id};else if(t.type===2)return{eventType:"MESSAGE_DEFERRED",id:t.id,dequeueAt:Number(t.dequeue_at)};else throw Error("Unknown event type")};var __filename="/home/runner/work/lonnymq/lonnymq/src/install/function-epoch.ts",b={name:_(__filename),sql:(e)=>{return[n`
655
- CREATE FUNCTION ${s(e.schema)}."epoch" ()
656
- RETURNS BIGINT AS $$
657
- DECLARE
658
- v_now TIMESTAMPTZ;
659
- BEGIN
660
- v_now := NOW();
661
- RETURN
662
- EXTRACT(EPOCH FROM v_now)::BIGINT * 1_000 +
663
- EXTRACT(MILLISECOND FROM v_now)::BIGINT;
664
- END;
665
- $$ LANGUAGE plpgsql;
666
- `]}};class D{schema;message;adaptor;constructor(e){this.schema=e.schema,this.adaptor=e.adaptor?e.adaptor:(t)=>t,this.message=new g({schema:this.schema,adaptor:this.adaptor})}async dequeue(e){let t=new o({schema:this.schema,lockMs:e.lockMs}),a=this.adaptor(e.databaseClient),E=await t.execute(a);if(E.resultType==="MESSAGE_DEQUEUED")return{resultType:"MESSAGE_DEQUEUED",message:new p({schema:this.schema,adaptor:this.adaptor,id:E.id,channelId:E.channelId,isUnlocked:E.isUnlocked,content:E.content,state:E.state,numAttempts:E.numAttempts})};else return E}channel(e){return new A({adaptor:this.adaptor,schema:this.schema,channelId:e})}install(e={}){return[v,M,C,b,q,G,L,O,U,f,$].sort((t,a)=>t.name.localeCompare(a.name)).flatMap((t)=>t.sql({schema:this.schema,eventChannel:e.eventChannel??null})).map((t)=>y(t.value))}static decode(e){return F(e)}}