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.d.mts +314 -0
- package/dist/index.mjs +1117 -0
- package/package.json +21 -17
- package/README.md +0 -356
- package/dist/index.cjs +0 -666
- package/dist/index.d.ts +0 -281
- package/dist/index.js +0 -666
package/dist/index.js
DELETED
|
@@ -1,666 +0,0 @@
|
|
|
1
|
-
var E=(e)=>({nodeType:"VALUE",value:e}),s=(e)=>({nodeType:"REF",value:e}),F=(e)=>({nodeType:"RAW",value:e}),b=(e)=>{return`'${e.replace(/'/g,"''")}'`},B=(e)=>{if(e===null)return"NULL";else if(typeof e==="string")return b(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}`)},H=(e)=>{return`"${e.replace(/"/g,'""')}"`},w=(e)=>{if(e.nodeType==="VALUE")return B(e.value);else if(e.nodeType==="REF")return H(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 r=0;r<e.length;r+=1)if(a.push(e[r]),r<t.length)a.push(w(t[r]));return F(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 r=e.releaseIntervalMs??null;this.releaseIntervalMs=r!==null?Math.max(0,r):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 p=(e)=>{let t=e.split(`
|
|
47
|
-
`),a=Number.MAX_SAFE_INTEGER;for(let r of t){if(r.trim().length===0)continue;let $=r.search(/\S/);a=Math.min(a,$)}return t.map((r)=>r.slice(a)).join(`
|
|
48
|
-
`).trim()};import{dirname as g}from"path";var __filename="/home/runner/work/lonnymq/lonnymq/src/core/path.ts",W=g(g(__filename)),Y=new RegExp(`^${W}/`),_=(e)=>{return e.replace(Y,"")};var __filename="/home/runner/work/lonnymq/lonnymq/src/install/table-channel-policy.ts",D={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",I={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",y={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",v={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
|
-
${E(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 ${E(e.eventChannel!==null)} THEN
|
|
217
|
-
PERFORM PG_NOTIFY(
|
|
218
|
-
${E(e.eventChannel)},
|
|
219
|
-
JSON_BUILD_OBJECT(
|
|
220
|
-
'type', ${E(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
|
-
${E(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",X=(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
|
-
`,J=(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
|
-
`,K=(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
|
-
`,M={name:_(__filename),sql:(e)=>{let t=X({now:n`v_now`,schema:e.schema}),a=K({channelId:n`v_channel_state."id"`,schema:e.schema}),r=J({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
|
-
${E(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
|
-
${r}
|
|
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
|
-
${E(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
|
-
${E(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",C={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
|
-
${E(0)};
|
|
404
|
-
RETURN;
|
|
405
|
-
ELSIF NOT v_message."is_locked" OR v_message."num_attempts" <> p_num_attempts THEN
|
|
406
|
-
RETURN QUERY SELECT
|
|
407
|
-
${E(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 ${E(e.eventChannel!==null)} THEN
|
|
438
|
-
PERFORM PG_NOTIFY(
|
|
439
|
-
${E(e.eventChannel)},
|
|
440
|
-
JSON_BUILD_OBJECT(
|
|
441
|
-
'type', ${E(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
|
-
${E(2)};
|
|
452
|
-
RETURN;
|
|
453
|
-
END;
|
|
454
|
-
$$ LANGUAGE plpgsql;
|
|
455
|
-
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/install/function-message-defer.ts",L={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
|
-
${E(0)};
|
|
486
|
-
RETURN;
|
|
487
|
-
ELSIF NOT v_message."is_locked" OR v_message."num_attempts" <> p_num_attempts THEN
|
|
488
|
-
RETURN QUERY SELECT
|
|
489
|
-
${E(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 ${E(e.eventChannel!==null)} THEN
|
|
533
|
-
PERFORM PG_NOTIFY(
|
|
534
|
-
${E(e.eventChannel)},
|
|
535
|
-
JSON_BUILD_OBJECT(
|
|
536
|
-
'type', ${E(2)},
|
|
537
|
-
'dequeue_at', v_dequeue_at,
|
|
538
|
-
'id', p_id::TEXT
|
|
539
|
-
)::TEXT
|
|
540
|
-
);
|
|
541
|
-
END IF;
|
|
542
|
-
|
|
543
|
-
RETURN QUERY SELECT
|
|
544
|
-
${E(2)};
|
|
545
|
-
RETURN;
|
|
546
|
-
END;
|
|
547
|
-
$$ LANGUAGE plpgsql;
|
|
548
|
-
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/install/function-channel-policy-clear.ts",O={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",U={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 h{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 R{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 S{policy;message;constructor(e){this.message=new h({schema:e.schema,adaptor:e.adaptor,channelId:e.channelId}),this.policy=new R({schema:e.schema,adaptor:e.adaptor,channelId:e.channelId})}}class N{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)}}import{randomUUID as j}from"crypto";class A{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:j()}).execute(t)}}var __filename="/home/runner/work/lonnymq/lonnymq/src/install/function-message-heartbeat.ts",f={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
|
-
${E(0)};
|
|
635
|
-
RETURN;
|
|
636
|
-
ELSIF NOT v_message."is_locked" OR v_message."num_attempts" <> p_num_attempts THEN
|
|
637
|
-
RETURN QUERY SELECT
|
|
638
|
-
${E(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
|
-
${E(2)};
|
|
651
|
-
RETURN;
|
|
652
|
-
END;
|
|
653
|
-
$$ LANGUAGE plpgsql;
|
|
654
|
-
`]}};var G=(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",q={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 x{schema;message;adaptor;constructor(e){this.schema=e.schema,this.adaptor=e.adaptor?e.adaptor:(t)=>t,this.message=new A({schema:this.schema,adaptor:this.adaptor})}async dequeue(e){let t=new o({schema:this.schema,lockMs:e.lockMs}),a=this.adaptor(e.databaseClient),r=await t.execute(a);if(r.resultType==="MESSAGE_DEQUEUED")return{resultType:"MESSAGE_DEQUEUED",message:new N({schema:this.schema,adaptor:this.adaptor,id:r.id,channelId:r.channelId,isUnlocked:r.isUnlocked,content:r.content,state:r.state,numAttempts:r.numAttempts})};else return r}channel(e){return new S({adaptor:this.adaptor,schema:this.schema,channelId:e})}install(e={}){return[D,I,y,q,U,O,v,M,C,L,f].sort((t,a)=>t.name.localeCompare(a.name)).flatMap((t)=>t.sql({schema:this.schema,eventChannel:e.eventChannel??null})).map((t)=>p(t.value))}static decode(e){return G(e)}}export{x as Queue,m as MessageHeartbeatCommand,o as MessageDequeueCommand,i as MessageDeleteCommand,d as MessageDeferCommand,l as MessageCreateCommand,u as ChannelPolicySetCommand,c as ChannelPolicyClearCommand};
|