lonnymq 0.0.19 → 0.0.20
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 +118 -44
- package/dist/index.cjs +29 -29
- package/dist/index.d.ts +54 -21
- package/dist/index.js +19 -19
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,12 +5,11 @@ A high-performance, multi-tenant PostgreSQL message queue implementation for Nod
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- High throughput message processing
|
|
8
|
-
- Multi-tenant concurrency and
|
|
8
|
+
- Multi-tenant concurrency and rate limits
|
|
9
9
|
- Durable message processing with automatic recovery
|
|
10
10
|
- Flexible message processing retries and deferrals
|
|
11
|
-
- Message deduplication
|
|
12
11
|
- Queue operations as part of *existing* database transactions
|
|
13
|
-
- Database client agnostic
|
|
12
|
+
- Database client agnostic with optional adapters
|
|
14
13
|
- Granular events via PostgreSQL `NOTIFY`
|
|
15
14
|
- Zero dependencies
|
|
16
15
|
|
|
@@ -34,22 +33,18 @@ for (const migration of queue.migrations()) {
|
|
|
34
33
|
|
|
35
34
|
// Create messages
|
|
36
35
|
for (let ix = 0; ix < 500; ix += 1) {
|
|
37
|
-
await queue
|
|
38
|
-
|
|
39
|
-
.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
databaseClient,
|
|
43
|
-
})
|
|
36
|
+
await queue.message.create({
|
|
37
|
+
databaseClient,
|
|
38
|
+
content: Buffer.from("Hello"),
|
|
39
|
+
lockMs: 30_000
|
|
40
|
+
})
|
|
44
41
|
}
|
|
45
42
|
|
|
46
43
|
// Process messages
|
|
47
44
|
while (true) {
|
|
48
45
|
const dequeueResult = await queue.dequeue({ databaseClient })
|
|
49
46
|
if (dequeueResult.resultType === "MESSAGE_NOT_AVAILABLE") {
|
|
50
|
-
|
|
51
|
-
await new Promise(resolve => setTimeout(resolve, sleepMs))
|
|
52
|
-
continue
|
|
47
|
+
break
|
|
53
48
|
}
|
|
54
49
|
|
|
55
50
|
console.log(dequeueResult.message.content.toString())
|
|
@@ -90,7 +85,7 @@ try {
|
|
|
90
85
|
|
|
91
86
|
Channels provide LonnyMQ's multi-tenancy support. They can be considered lightweight sub-queues that are read from in round-robin fashion. There is no performance penalty for using large numbers of channels, so they can be assigned on a highly granular basis (e.g., per-user) to ensure work is scheduled fairly.
|
|
92
87
|
|
|
93
|
-
Channels can be configured with concurrency
|
|
88
|
+
Channels can be configured with concurrency and rate limits by setting their "channel policy":
|
|
94
89
|
|
|
95
90
|
```typescript
|
|
96
91
|
await queue
|
|
@@ -99,7 +94,6 @@ await queue
|
|
|
99
94
|
.set({
|
|
100
95
|
databaseClient,
|
|
101
96
|
maxConcurrency: 1,
|
|
102
|
-
maxSize: 100,
|
|
103
97
|
releaseIntervalMs: 1000
|
|
104
98
|
})
|
|
105
99
|
|
|
@@ -112,7 +106,18 @@ await queue
|
|
|
112
106
|
|
|
113
107
|
## Message Creation
|
|
114
108
|
|
|
115
|
-
You can add a message to the queue
|
|
109
|
+
You can add a message to the queue using the `create` function. By default, messages are assigned to a random channel, ensuring fair distribution:
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
await queue.message.create({
|
|
113
|
+
databaseClient,
|
|
114
|
+
content: Buffer.from("Hello, world"),
|
|
115
|
+
lockMs: 30000,
|
|
116
|
+
delayMs: 5000
|
|
117
|
+
})
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
If you need to assign messages to specific channels (for example, to take advantage of concurrency or rate limiting features), you can specify the channel explicitly:
|
|
116
121
|
|
|
117
122
|
```typescript
|
|
118
123
|
await queue
|
|
@@ -121,25 +126,27 @@ await queue
|
|
|
121
126
|
.create({
|
|
122
127
|
databaseClient,
|
|
123
128
|
content: Buffer.from("Hello, world"),
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
delayMs: 5000 // 5 second delay
|
|
129
|
+
lockMs: 30000,
|
|
130
|
+
delayMs: 5000
|
|
127
131
|
})
|
|
128
132
|
```
|
|
129
133
|
|
|
130
|
-
The `
|
|
134
|
+
The `lockMs` parameter is required and specifies how long a message will remain exclusively locked after being dequeued. While locked, the message is **not available** for subsequent `dequeue()` calls, preventing duplicate processing. If your process crashes or takes longer than expected, the message will automatically become available for dequeue again after the lock expires.
|
|
135
|
+
|
|
136
|
+
The `delayMs` parameter is optional and allows you to delay when the message becomes available for processing.
|
|
131
137
|
|
|
132
138
|
## Message Processing
|
|
133
139
|
|
|
134
140
|
Messages can be fetched for processing by calling `dequeue` on the `Queue` - this locks the message. Once processing is complete, messages must be "finalized" via **deletion** or **deferral** (for further processing in the future).
|
|
135
141
|
|
|
136
142
|
```typescript
|
|
143
|
+
const dequeueResult = await queue.dequeue({ databaseClient })
|
|
137
144
|
|
|
138
145
|
if (dequeueResult.resultType === "MESSAGE_DEQUEUED") {
|
|
139
146
|
const { message } = dequeueResult
|
|
140
147
|
console.log(`Processing message: ${message.id}`)
|
|
141
148
|
console.log(`Content: ${message.content.toString()}`)
|
|
142
|
-
console.log(`
|
|
149
|
+
console.log(`State: ${message.state?.toString()}`)
|
|
143
150
|
|
|
144
151
|
try {
|
|
145
152
|
// Process the message...
|
|
@@ -148,18 +155,61 @@ if (dequeueResult.resultType === "MESSAGE_DEQUEUED") {
|
|
|
148
155
|
// Delete on success
|
|
149
156
|
await message.delete({ databaseClient })
|
|
150
157
|
} catch (error) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
databaseClient
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
158
|
+
if (message.numAttempts >= 5) {
|
|
159
|
+
// Too many retries, delete permanently
|
|
160
|
+
await message.delete({ databaseClient })
|
|
161
|
+
} else {
|
|
162
|
+
// Defer for retry with exponential backoff and updated state
|
|
163
|
+
const backoffMs = Math.pow(2, message.numAttempts) * 1000
|
|
164
|
+
await message.defer({
|
|
165
|
+
databaseClient,
|
|
166
|
+
delayMs: backoffMs,
|
|
167
|
+
state: Buffer.from(JSON.stringify({
|
|
168
|
+
error: error.message,
|
|
169
|
+
lastAttempt: new Date().toISOString()
|
|
170
|
+
}))
|
|
171
|
+
})
|
|
172
|
+
}
|
|
157
173
|
}
|
|
174
|
+
} else {
|
|
175
|
+
console.log("No messages available")
|
|
158
176
|
}
|
|
159
177
|
```
|
|
160
178
|
|
|
161
179
|
When deferring a message, you can optionally specify `delayMs` and `state` arguments. The `delayMs` parameter tells the queue how long to wait before making the message available for reprocessing, and `state` allows you to "save your work" and implement durable and/or repeating/scheduled tasks.
|
|
162
180
|
|
|
181
|
+
**Note:** The above shows just one processing pattern (defer on failure with retry limits). You have complete flexibility in how you handle message processing - you might delete messages immediately, defer them unconditionally, implement different retry strategies based on error types, or use the message metadata (attempts, state, channel) to make sophisticated routing decisions.
|
|
182
|
+
|
|
183
|
+
### Message Heartbeats
|
|
184
|
+
|
|
185
|
+
For long-running message processing, you can use the heartbeat functionality to extend the lock time beyond the initial `lockMs` value. This is useful when you need to process a message for longer than originally anticipated but want to keep a shorter default lock time for faster recovery.
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
const dequeueResult = await queue.dequeue({ databaseClient })
|
|
189
|
+
|
|
190
|
+
if (dequeueResult.resultType === "MESSAGE_DEQUEUED") {
|
|
191
|
+
const { message } = dequeueResult
|
|
192
|
+
|
|
193
|
+
// Start a long-running process
|
|
194
|
+
const intervalId = setInterval(async () => {
|
|
195
|
+
// Send heartbeat every 10 seconds to keep the message locked
|
|
196
|
+
await message.heartbeat({ databaseClient })
|
|
197
|
+
}, 10000)
|
|
198
|
+
|
|
199
|
+
try {
|
|
200
|
+
// Process the message (this might take a long time)
|
|
201
|
+
await longRunningProcessMessage(message.content)
|
|
202
|
+
await message.delete({ databaseClient })
|
|
203
|
+
} catch (error) {
|
|
204
|
+
await message.defer({ databaseClient, delayMs: 30000 })
|
|
205
|
+
} finally {
|
|
206
|
+
clearInterval(intervalId)
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Heartbeats reset the unlock time to the current time plus the original `lockMs` value.
|
|
212
|
+
|
|
163
213
|
### Graceful Shutdowns and Message Recovery
|
|
164
214
|
|
|
165
215
|
If your program ends unexpectedly, messages that are currently being processed may become "orphaned" in a locked state - causing channel blockages and reducing throughput. To mitigate this problem, it's essential that you shut down gracefully by catching unhandled exceptions and signals (i.e., `SIGINT`/`SIGTERM`) and finalize all outstanding messages before exiting.
|
|
@@ -206,7 +256,7 @@ client.on("notification", (msg) => {
|
|
|
206
256
|
|
|
207
257
|
### Waiting for Job Completion
|
|
208
258
|
|
|
209
|
-
The `MESSAGE_DELETED` event can be used to create coordination patterns where one part of your application waits for an unrelated job to complete. By listening for deletion events on specific
|
|
259
|
+
The `MESSAGE_DELETED` event can be used to create coordination patterns where one part of your application waits for an unrelated job to complete. By listening for deletion events on specific message IDs, you can implement blocking operations that wait for background work to finish.
|
|
210
260
|
|
|
211
261
|
```typescript
|
|
212
262
|
const client = await databaseClient.connect()
|
|
@@ -217,9 +267,7 @@ const wait = (messageId: string) : Promise<void> => {
|
|
|
217
267
|
const handler = (msg) => {
|
|
218
268
|
if (msg.channel === "EVENTS") {
|
|
219
269
|
const event = queueEventDecode(msg.payload as string)
|
|
220
|
-
if (event.eventType === "MESSAGE_DELETED" &&
|
|
221
|
-
event.channelName === "background-jobs" &&
|
|
222
|
-
event.messageName === messageId) {
|
|
270
|
+
if (event.eventType === "MESSAGE_DELETED" && event.id === messageId) {
|
|
223
271
|
client.off("notification", handler)
|
|
224
272
|
resolve()
|
|
225
273
|
}
|
|
@@ -234,7 +282,7 @@ await wait(messageId)
|
|
|
234
282
|
|
|
235
283
|
## Deadlocks
|
|
236
284
|
|
|
237
|
-
If all queue actions are isolated to their own transaction, there is zero risk of deadlocks occurring. That being said, it is *possible* to safely bulk-perform the following actions within a single transaction if we ensure they are performed in a consistent lexicographical ordering with respect to channel name
|
|
285
|
+
If all queue actions are isolated to their own transaction, there is zero risk of deadlocks occurring. That being said, it is *possible* to safely bulk-perform the following actions within a single transaction if we ensure they are performed in a consistent lexicographical ordering with respect to channel name:
|
|
238
286
|
|
|
239
287
|
- Message create
|
|
240
288
|
- Channel policy set
|
|
@@ -245,38 +293,43 @@ Beyond the actions specified above, it is manifestly **unsafe** to bulk-perform
|
|
|
245
293
|
- Message dequeue
|
|
246
294
|
- Message defer
|
|
247
295
|
- Message delete
|
|
296
|
+
- Message heartbeat
|
|
248
297
|
|
|
249
298
|
## Batching Operations
|
|
250
299
|
|
|
251
300
|
When you need to perform multiple safe operations (message creation and channel policy changes) within a single transaction, LonnyMQ provides a batching mechanism that automatically handles proper ordering to prevent deadlocks.
|
|
252
301
|
|
|
253
|
-
The batch interface mirrors
|
|
254
|
-
|
|
255
|
-
The batch system ensures that all operations are executed in a consistent lexicographical order based on channel name and message name, eliminating the possibility of deadlocks when multiple workers are performing bulk operations simultaneously.
|
|
302
|
+
The batch interface mirrors a subset of the queue interface, supporting only the operations that are safe to perform together: message creation and channel policy management.
|
|
256
303
|
|
|
257
304
|
```typescript
|
|
258
305
|
const batch = queue.batch()
|
|
259
306
|
|
|
260
|
-
|
|
261
|
-
|
|
307
|
+
// Create messages (assigned to random channels)
|
|
308
|
+
batch.message.create({
|
|
309
|
+
content: Buffer.from("Welcome email"),
|
|
310
|
+
lockMs: 30000
|
|
262
311
|
})
|
|
263
312
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
313
|
+
// Create messages on specific channels
|
|
314
|
+
batch.channel("user-notifications").message.create({
|
|
315
|
+
content: Buffer.from("User signup notification"),
|
|
316
|
+
lockMs: 60000
|
|
268
317
|
})
|
|
269
318
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
319
|
+
// Set channel policies
|
|
320
|
+
batch.channel("high-priority").policy.set({
|
|
321
|
+
maxConcurrency: 5,
|
|
322
|
+
releaseIntervalMs: 100
|
|
273
323
|
})
|
|
274
324
|
|
|
325
|
+
// Clear channel policies
|
|
275
326
|
batch.channel("analytics").policy.clear()
|
|
276
327
|
|
|
277
328
|
await batch.execute({ databaseClient })
|
|
278
329
|
```
|
|
279
330
|
|
|
331
|
+
The batch system ensures all operations are executed in a consistent lexicographical order, eliminating the possibility of deadlocks when multiple workers are performing bulk operations simultaneously.
|
|
332
|
+
|
|
280
333
|
## Database Clients
|
|
281
334
|
|
|
282
335
|
LonnyMQ is designed to be database client agnostic, requiring only a minimal interface that most PostgreSQL clients already implement. Your database client must provide a single `query` method with this signature:
|
|
@@ -287,4 +340,25 @@ interface DatabaseClient {
|
|
|
287
340
|
rows: Array<Record<string, unknown>>
|
|
288
341
|
}>
|
|
289
342
|
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### Database Client Adapters
|
|
346
|
+
|
|
347
|
+
For database clients that don't match the expected interface exactly, LonnyMQ provides an adapter system to improve the developer experience. You can provide an adapter function when creating a Queue:
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
import { Queue } from "lonnymq"
|
|
351
|
+
import { Pool } from "pg"
|
|
352
|
+
|
|
353
|
+
const customClient = new SomeOtherPostgresClient()
|
|
354
|
+
const queue = new Queue({
|
|
355
|
+
schema: "lonny",
|
|
356
|
+
adaptor: (client) => ({
|
|
357
|
+
query: async (sql, params) => {
|
|
358
|
+
// Adapt the client's interface to match DatabaseClient
|
|
359
|
+
const result = await client.executeQuery(sql, params)
|
|
360
|
+
return { rows: result.data }
|
|
361
|
+
}
|
|
362
|
+
})
|
|
363
|
+
})
|
|
290
364
|
```
|
package/dist/index.cjs
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
var{defineProperty:
|
|
1
|
+
var{defineProperty:h,getOwnPropertyNames:z,getOwnPropertyDescriptor:J}=Object,X=Object.prototype.hasOwnProperty;var U=new WeakMap,K=(e)=>{var t=U.get(e),n;if(t)return t;if(t=h({},"__esModule",{value:!0}),e&&typeof e==="object"||typeof e==="function")z(e).map((r)=>!X.call(t,r)&&h(t,r,{get:()=>e[r],enumerable:!(n=J(e,r))||n.enumerable}));return U.set(e,t),t};var j=(e,t)=>{for(var n in t)h(e,n,{get:t[n],enumerable:!0,configurable:!0,set:(r)=>t[n]=()=>r})};var de={};j(de,{queueEventDecode:()=>f,Queue:()=>C,MessageHeartbeatCommand:()=>d,MessageDequeueCommand:()=>m,MessageDeleteCommand:()=>i,MessageDeferCommand:()=>u,MessageCreateCommand:()=>o,ChannelPolicySetCommand:()=>l,ChannelPolicyClearCommand:()=>c});module.exports=K(de);var O=(e)=>{return e*1000};var T=O(0);var f=(e)=>{let t=JSON.parse(e);if(t.type===0)return{eventType:"MESSAGE_CREATED",id:t.id,delayMs:t.delay_ms};else if(t.type===1)return{eventType:"MESSAGE_DELETED",id:t.id};else if(t.type===2)return{eventType:"MESSAGE_DEFERRED",id:t.id,delayMs:t.delay_ms};else throw new Error("Unknown event type")};var _=(e)=>({nodeType:"VALUE",value:e}),s=(e)=>({nodeType:"REF",value:e}),Z=(e)=>({nodeType:"RAW",value:e}),ee=(e)=>{return`'${e.replace(/'/g,"''")}'`},te=(e)=>{if(e===null)return"NULL";else if(typeof e==="string")return ee(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 new Error(`Unsupported value type: ${typeof e}`)},se=(e)=>{return`"${e.replace(/"/g,'""')}"`},ne=(e)=>{if(e.nodeType==="VALUE")return te(e.value);else if(e.nodeType==="REF")return se(e.value);else if(e.nodeType==="RAW")return e.value;else throw new Error("Unsupported SQL node type")};var a=(e,...t)=>{let n=[];for(let r=0;r<e.length;r+=1)if(n.push(e[r]),r<t.length)n.push(ne(t[r]));return Z(n.join(""))};class c{schema;channelName;createdAt;constructor(e){this.schema=e.schema,this.channelName=e.channelName,this.createdAt=new Date}async execute(e){await e.query(a`
|
|
2
2
|
SELECT 1 FROM ${s(this.schema)}."channel_policy_clear"(
|
|
3
3
|
$1
|
|
4
4
|
)
|
|
5
|
-
`.value,[this.channelName])}}class
|
|
5
|
+
`.value,[this.channelName])}}class l{schema;channelName;maxConcurrency;releaseIntervalMs;createdAt;constructor(e){this.schema=e.schema,this.channelName=e.channelName;let t=e.maxConcurrency??null;this.maxConcurrency=t!==null?Math.max(0,t):null;let n=e.releaseIntervalMs??null;this.releaseIntervalMs=n!==null?Math.max(0,n):null,this.createdAt=new Date}async execute(e){await e.query(a`
|
|
6
6
|
SELECT 1 FROM ${s(this.schema)}."channel_policy_set"(
|
|
7
7
|
$1,
|
|
8
8
|
$2::INTEGER,
|
|
9
9
|
$3::INTEGER
|
|
10
10
|
)
|
|
11
|
-
`.value,[this.channelName,this.maxConcurrency,this.releaseIntervalMs])}}var
|
|
11
|
+
`.value,[this.channelName,this.maxConcurrency,this.releaseIntervalMs])}}var F=require("crypto"),x=()=>{return F.randomBytes(16).toString("base64url")};var G=require("node:crypto");class o{schema;channelName;content;lockMs;id;delayMs;createdAt;constructor(e){let t=Math.max(0,e.lockMs),n=e.delayMs===void 0?T:e.delayMs;this.id=G.randomUUID(),this.schema=e.schema,this.channelName=e.channelName??x(),this.content=e.content,this.lockMs=t,this.delayMs=n,this.createdAt=new Date}async execute(e){await e.query(a`
|
|
12
12
|
SELECT 1 FROM ${s(this.schema)}."message_create"(
|
|
13
13
|
$1,
|
|
14
14
|
$2,
|
|
@@ -16,33 +16,33 @@ var{defineProperty:N,getOwnPropertyNames:Q,getOwnPropertyDescriptor:V}=Object,W=
|
|
|
16
16
|
$4::BIGINT,
|
|
17
17
|
$5::BIGINT
|
|
18
18
|
)
|
|
19
|
-
`.value,[this.id,this.channelName,this.content,this.lockMs,this.delayMs])}}class m{schema;constructor(e){this.schema=e.schema}async execute(e){let t=await e.query(
|
|
19
|
+
`.value,[this.id,this.channelName,this.content,this.lockMs,this.delayMs])}}class m{schema;constructor(e){this.schema=e.schema}async execute(e){let t=await e.query(a`
|
|
20
20
|
SELECT
|
|
21
21
|
result_code,
|
|
22
22
|
metadata,
|
|
23
23
|
content,
|
|
24
24
|
state
|
|
25
25
|
FROM ${s(this.schema)}."message_dequeue"()
|
|
26
|
-
`.value,[]).then((
|
|
26
|
+
`.value,[]).then((n)=>n.rows[0]);if(t.result_code===0)return{resultType:"MESSAGE_NOT_AVAILABLE",retryMs:t.metadata.retry_ms};else if(t.result_code===1)return{resultType:"MESSAGE_DEQUEUED",message:{id:t.metadata.id,channelName:t.metadata.channel_name,isUnlocked:t.metadata.is_unlocked,content:t.content,state:t.state,numAttempts:t.metadata.num_attempts}};else throw new 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(a`
|
|
27
27
|
SELECT * FROM ${s(this.schema)}."message_delete"(
|
|
28
28
|
$1,
|
|
29
29
|
$2::BIGINT
|
|
30
30
|
)
|
|
31
|
-
`.value,[this.id,this.numAttempts]).then((
|
|
31
|
+
`.value,[this.id,this.numAttempts]).then((n)=>n.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 new Error("Unexpected result")}}class u{schema;id;numAttempts;delayMs;state;constructor(e){let t=e.delayMs===void 0?T:e.delayMs;this.schema=e.schema,this.numAttempts=e.numAttempts,this.id=e.id,this.delayMs=t,this.state=e.state??null}async execute(e){let t=await e.query(a`
|
|
32
32
|
SELECT * FROM ${s(this.schema)}."message_defer"(
|
|
33
33
|
$1,
|
|
34
34
|
$2::BIGINT,
|
|
35
35
|
$3::BIGINT,
|
|
36
36
|
$4
|
|
37
37
|
)
|
|
38
|
-
`.value,[this.id,this.numAttempts,this.delayMs,this.state]).then((
|
|
38
|
+
`.value,[this.id,this.numAttempts,this.delayMs,this.state]).then((n)=>n.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 new Error("Unexpected result")}}class d{schema;id;numAttempts;constructor(e){this.schema=e.schema,this.numAttempts=e.numAttempts,this.id=e.id}async execute(e){let t=await e.query(a`
|
|
39
39
|
SELECT * FROM ${s(this.schema)}."message_heartbeat"(
|
|
40
40
|
$1,
|
|
41
41
|
$2::BIGINT
|
|
42
42
|
)
|
|
43
|
-
`.value,[this.id,this.numAttempts]).then((
|
|
44
|
-
`),
|
|
45
|
-
`).trim()};var
|
|
43
|
+
`.value,[this.id,this.numAttempts]).then((n)=>n.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 new Error("Unexpected result")}}var q=(e)=>{let t=e.split(`
|
|
44
|
+
`),n=Number.MAX_SAFE_INTEGER;for(let r of t){if(r.trim().length===0)continue;let Y=r.search(/\S/);n=Math.min(n,Y)}return t.map((r)=>r.slice(n)).join(`
|
|
45
|
+
`).trim()};var g=require("path"),__filename="/home/runner/work/lonnymq/lonnymq/src/core/path.ts",oe=g.dirname(g.dirname(__filename)),ce=new RegExp(`^${oe}/`),E=(e)=>{return e.replace(ce,"")};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/00-table-channel-policy.ts",$={name:E(__filename),sql:(e)=>{return[a`
|
|
46
46
|
CREATE TABLE ${s(e.schema)}."channel_policy" (
|
|
47
47
|
"id" UUID NOT NULL DEFAULT GEN_RANDOM_UUID(),
|
|
48
48
|
"name" TEXT NOT NULL,
|
|
@@ -51,10 +51,10 @@ var{defineProperty:N,getOwnPropertyNames:Q,getOwnPropertyDescriptor:V}=Object,W=
|
|
|
51
51
|
"created_at" TIMESTAMP NOT NULL,
|
|
52
52
|
PRIMARY KEY ("id")
|
|
53
53
|
);
|
|
54
|
-
`,
|
|
54
|
+
`,a`
|
|
55
55
|
CREATE UNIQUE INDEX "channel_policy_name_ux"
|
|
56
56
|
ON ${s(e.schema)}."channel_policy" ("name");
|
|
57
|
-
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/01-table-channel-state.ts",
|
|
57
|
+
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/01-table-channel-state.ts",b={name:E(__filename),sql:(e)=>{return[a`
|
|
58
58
|
CREATE TABLE ${s(e.schema)}."channel_state" (
|
|
59
59
|
"id" UUID NOT NULL DEFAULT GEN_RANDOM_UUID(),
|
|
60
60
|
"name" TEXT NOT NULL,
|
|
@@ -70,16 +70,16 @@ var{defineProperty:N,getOwnPropertyNames:Q,getOwnPropertyDescriptor:V}=Object,W=
|
|
|
70
70
|
"created_at" TIMESTAMP NOT NULL,
|
|
71
71
|
PRIMARY KEY ("id")
|
|
72
72
|
);
|
|
73
|
-
`,
|
|
73
|
+
`,a`
|
|
74
74
|
CREATE UNIQUE INDEX "channel_state_name_ux"
|
|
75
75
|
ON ${s(e.schema)}."channel_state" ("name");
|
|
76
|
-
`,
|
|
76
|
+
`,a`
|
|
77
77
|
CREATE INDEX "channel_state_dequeue_ix"
|
|
78
78
|
ON ${s(e.schema)}."channel_state" (
|
|
79
79
|
"active_next_at" ASC
|
|
80
80
|
) WHERE "message_id" IS NOT NULL
|
|
81
81
|
AND ("max_concurrency" IS NULL OR "current_concurrency" < "max_concurrency");
|
|
82
|
-
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/02-table-message.ts",
|
|
82
|
+
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/02-table-message.ts",B={name:E(__filename),sql:(e)=>{return[a`
|
|
83
83
|
CREATE TABLE ${s(e.schema)}."message" (
|
|
84
84
|
"id" UUID NOT NULL,
|
|
85
85
|
"channel_name" TEXT NOT NULL,
|
|
@@ -94,19 +94,19 @@ var{defineProperty:N,getOwnPropertyNames:Q,getOwnPropertyDescriptor:V}=Object,W=
|
|
|
94
94
|
"created_at" TIMESTAMP NOT NULL,
|
|
95
95
|
PRIMARY KEY ("id")
|
|
96
96
|
);
|
|
97
|
-
`,
|
|
97
|
+
`,a`
|
|
98
98
|
CREATE INDEX "message_dequeue_ix"
|
|
99
99
|
ON ${s(e.schema)}."message" (
|
|
100
100
|
"channel_name",
|
|
101
101
|
"dequeue_at" ASC,
|
|
102
102
|
"seq_no" ASC
|
|
103
103
|
) WHERE NOT "is_locked";
|
|
104
|
-
`,
|
|
104
|
+
`,a`
|
|
105
105
|
CREATE INDEX "message_locked_dequeue_ix"
|
|
106
106
|
ON ${s(e.schema)}."message" (
|
|
107
107
|
"unlock_at" ASC
|
|
108
108
|
) WHERE "is_locked";
|
|
109
|
-
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/03-function-message-create.ts"
|
|
109
|
+
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/03-function-message-create.ts",k={name:E(__filename),sql:(e)=>{return[a`
|
|
110
110
|
CREATE FUNCTION ${s(e.schema)}."message_create" (
|
|
111
111
|
p_id UUID,
|
|
112
112
|
p_channel_name TEXT,
|
|
@@ -217,7 +217,7 @@ var{defineProperty:N,getOwnPropertyNames:Q,getOwnPropertyDescriptor:V}=Object,W=
|
|
|
217
217
|
END IF;
|
|
218
218
|
END;
|
|
219
219
|
$$ LANGUAGE plpgsql;
|
|
220
|
-
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/04-function-message-dequeue.ts",
|
|
220
|
+
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/04-function-message-dequeue.ts",le=(e)=>a`
|
|
221
221
|
SELECT
|
|
222
222
|
"message"."id",
|
|
223
223
|
"message"."state",
|
|
@@ -230,7 +230,7 @@ var{defineProperty:N,getOwnPropertyNames:Q,getOwnPropertyDescriptor:V}=Object,W=
|
|
|
230
230
|
WHERE "is_locked"
|
|
231
231
|
AND "unlock_at" <= ${e.now}
|
|
232
232
|
ORDER BY "unlock_at" ASC
|
|
233
|
-
`,
|
|
233
|
+
`,me=(e)=>a`
|
|
234
234
|
SELECT
|
|
235
235
|
"channel_state"."id",
|
|
236
236
|
"channel_state"."name",
|
|
@@ -243,7 +243,7 @@ var{defineProperty:N,getOwnPropertyNames:Q,getOwnPropertyDescriptor:V}=Object,W=
|
|
|
243
243
|
WHERE "message_id" IS NOT NULL
|
|
244
244
|
AND ("max_concurrency" IS NULL OR "current_concurrency" < "max_concurrency")
|
|
245
245
|
ORDER BY "active_next_at" ASC
|
|
246
|
-
`,
|
|
246
|
+
`,ie=(e)=>a`
|
|
247
247
|
SELECT
|
|
248
248
|
"message"."id",
|
|
249
249
|
"message"."dequeue_at",
|
|
@@ -252,7 +252,7 @@ var{defineProperty:N,getOwnPropertyNames:Q,getOwnPropertyDescriptor:V}=Object,W=
|
|
|
252
252
|
WHERE NOT "is_locked"
|
|
253
253
|
AND "channel_name" = ${e.channelName}
|
|
254
254
|
ORDER BY "dequeue_at" ASC, "seq_no" ASC
|
|
255
|
-
`,
|
|
255
|
+
`,w={name:E(__filename),sql:(e)=>{let t=le({now:a`v_now`,schema:e.schema}),n=ie({channelName:a`v_channel_state."name"`,schema:e.schema}),r=me({schema:e.schema});return[a`
|
|
256
256
|
CREATE FUNCTION ${s(e.schema)}."message_dequeue" ()
|
|
257
257
|
RETURNS TABLE (
|
|
258
258
|
result_code INTEGER,
|
|
@@ -337,7 +337,7 @@ var{defineProperty:N,getOwnPropertyNames:Q,getOwnPropertyDescriptor:V}=Object,W=
|
|
|
337
337
|
"unlock_at" = v_now + (v_message_dequeue."lock_ms" * INTERVAL '1 millisecond')
|
|
338
338
|
WHERE "id" = v_message_dequeue."id";
|
|
339
339
|
|
|
340
|
-
${
|
|
340
|
+
${n}
|
|
341
341
|
LIMIT 1
|
|
342
342
|
INTO v_message_next;
|
|
343
343
|
|
|
@@ -374,7 +374,7 @@ var{defineProperty:N,getOwnPropertyNames:Q,getOwnPropertyDescriptor:V}=Object,W=
|
|
|
374
374
|
RETURN;
|
|
375
375
|
END;
|
|
376
376
|
$$ LANGUAGE plpgsql;
|
|
377
|
-
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/05-function-message-delete.ts",
|
|
377
|
+
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/05-function-message-delete.ts",H={name:E(__filename),sql:(e)=>{return[a`
|
|
378
378
|
CREATE FUNCTION ${s(e.schema)}."message_delete" (
|
|
379
379
|
p_id UUID,
|
|
380
380
|
p_num_attempts BIGINT
|
|
@@ -451,7 +451,7 @@ var{defineProperty:N,getOwnPropertyNames:Q,getOwnPropertyDescriptor:V}=Object,W=
|
|
|
451
451
|
RETURN;
|
|
452
452
|
END;
|
|
453
453
|
$$ LANGUAGE plpgsql;
|
|
454
|
-
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/06-function-message-defer.ts",P={name:E(__filename),sql:(e)=>{return[
|
|
454
|
+
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/06-function-message-defer.ts",P={name:E(__filename),sql:(e)=>{return[a`
|
|
455
455
|
CREATE FUNCTION ${s(e.schema)}."message_defer" (
|
|
456
456
|
p_id UUID,
|
|
457
457
|
p_num_attempts BIGINT,
|
|
@@ -547,7 +547,7 @@ var{defineProperty:N,getOwnPropertyNames:Q,getOwnPropertyDescriptor:V}=Object,W=
|
|
|
547
547
|
RETURN;
|
|
548
548
|
END;
|
|
549
549
|
$$ LANGUAGE plpgsql;
|
|
550
|
-
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/07-function-message-heartbeat.ts",
|
|
550
|
+
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/07-function-message-heartbeat.ts",Q={name:E(__filename),sql:(e)=>{return[a`
|
|
551
551
|
CREATE FUNCTION ${s(e.schema)}."message_heartbeat" (
|
|
552
552
|
p_id UUID,
|
|
553
553
|
p_num_attempts BIGINT
|
|
@@ -590,7 +590,7 @@ var{defineProperty:N,getOwnPropertyNames:Q,getOwnPropertyDescriptor:V}=Object,W=
|
|
|
590
590
|
RETURN;
|
|
591
591
|
END;
|
|
592
592
|
$$ LANGUAGE plpgsql;
|
|
593
|
-
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/08-function-channel-policy-clear.ts",
|
|
593
|
+
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/08-function-channel-policy-clear.ts",V={name:E(__filename),sql:(e)=>{return[a`
|
|
594
594
|
CREATE FUNCTION ${s(e.schema)}."channel_policy_clear" (
|
|
595
595
|
p_name TEXT
|
|
596
596
|
) RETURNS VOID AS $$
|
|
@@ -619,7 +619,7 @@ var{defineProperty:N,getOwnPropertyNames:Q,getOwnPropertyDescriptor:V}=Object,W=
|
|
|
619
619
|
END IF;
|
|
620
620
|
END;
|
|
621
621
|
$$ LANGUAGE plpgsql;
|
|
622
|
-
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/09-function-channel-policy-set.ts",
|
|
622
|
+
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/09-function-channel-policy-set.ts",W={name:E(__filename),sql:(e)=>{return[a`
|
|
623
623
|
CREATE FUNCTION ${s(e.schema)}."channel_policy_set" (
|
|
624
624
|
p_name TEXT,
|
|
625
625
|
p_max_concurrency INTEGER,
|
|
@@ -650,4 +650,4 @@ var{defineProperty:N,getOwnPropertyNames:Q,getOwnPropertyDescriptor:V}=Object,W=
|
|
|
650
650
|
WHERE "name" = p_name;
|
|
651
651
|
END;
|
|
652
652
|
$$ LANGUAGE plpgsql;
|
|
653
|
-
`]}};class S{schema;channelName;registerFn;constructor(e){this.schema=e.schema,this.channelName=e.channelName,this.registerFn=e.registerFn}create(e){let t=new
|
|
653
|
+
`]}};class S{schema;channelName;registerFn;constructor(e){this.schema=e.schema,this.channelName=e.channelName,this.registerFn=e.registerFn}create(e){let t=new o({schema:this.schema,channelName:this.channelName,content:e.content,lockMs:e.lockMs,delayMs:e.delayMs});return this.registerFn({sortKey:JSON.stringify([t.channelName,t.createdAt.toISOString()]),execute:(n)=>t.execute(n)}),{messageId:t.id}}}class R{schema;channelName;registerFn;constructor(e){this.schema=e.schema,this.channelName=e.channelName,this.registerFn=e.registerFn}set(e){let t=new l({schema:this.schema,channelName:this.channelName,maxConcurrency:e.maxConcurrency,releaseIntervalMs:e.releaseIntervalMs});this.registerFn({sortKey:JSON.stringify([t.channelName,t.createdAt.toISOString()]),execute:async(n)=>{await t.execute(n)}})}clear(){let e=new c({schema:this.schema,channelName:this.channelName});this.registerFn({sortKey:JSON.stringify([e.channelName,e.createdAt.toISOString()]),execute:async(t)=>{await e.execute(t)}})}}class A{policy;message;constructor(e){this.message=new S(e),this.policy=new R(e)}}class p{schema;registerFn;constructor(e){this.schema=e.schema,this.registerFn=e.registerFn}create(e){let t=new o({schema:this.schema,content:e.content,lockMs:e.lockMs,delayMs:e.delayMs});return this.registerFn({sortKey:JSON.stringify([t.channelName,t.createdAt.toISOString()]),execute:(n)=>t.execute(n)}),{messageId:t.id,channelName:t.channelName}}}var ue=(e,t)=>{return e.sortKey.localeCompare(t.sortKey)};class D{commands;schema;adaptor;message;constructor(e){this.schema=e.schema,this.adaptor=e.adaptor,this.commands=[],this.message=new p({schema:this.schema,registerFn:(t)=>this.commands.push(t)})}channel(e){return new A({schema:this.schema,channelName:e,registerFn:(t)=>this.commands.push(t)})}async execute(e){let t=this.adaptor(e.databaseClient);for(let n of this.commands.sort(ue))await n.execute(t)}}class y{schema;channelName;adaptor;constructor(e){this.schema=e.schema,this.adaptor=e.adaptor,this.channelName=e.channelName}async create(e){let t=this.adaptor(e.databaseClient),n=new o({schema:this.schema,channelName:this.channelName,content:e.content,lockMs:e.lockMs,delayMs:e.delayMs});return await n.execute(t),{messageId:n.id}}}class M{schema;adaptor;channelName;constructor(e){this.schema=e.schema,this.adaptor=e.adaptor,this.channelName=e.channelName}set(e){let t=this.adaptor(e.databaseClient);return new l({schema:this.schema,channelName:this.channelName,maxConcurrency:e.maxConcurrency,releaseIntervalMs:e.releaseIntervalMs}).execute(t)}clear(e){let t=this.adaptor(e.databaseClient);return new c({schema:this.schema,channelName:this.channelName}).execute(t)}}class v{policy;message;constructor(e){this.message=new y({schema:e.schema,adaptor:e.adaptor,channelName:e.channelName}),this.policy=new M({schema:e.schema,adaptor:e.adaptor,channelName:e.channelName})}}class I{schema;adaptor;id;isUnlocked;channelName;content;state;numAttempts;constructor(e){this.schema=e.schema,this.adaptor=e.adaptor,this.id=e.id,this.channelName=e.channelName,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 u({schema:this.schema,id:this.id,numAttempts:this.numAttempts,delayMs:e.delayMs,state:e.state}).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 d({schema:this.schema,id:this.id,numAttempts:this.numAttempts}).execute(t)}}class L{schema;adaptor;constructor(e){this.schema=e.schema,this.adaptor=e.adaptor}async create(e){let t=this.adaptor(e.databaseClient),n=new o({schema:this.schema,content:e.content,lockMs:e.lockMs,delayMs:e.delayMs});return await n.execute(t),{messageId:n.id,channelName:n.channelName}}}class C{schema;adaptor;message;constructor(e){this.schema=e.schema,this.adaptor=e.adaptor?e.adaptor:(t)=>t,this.message=new L({schema:this.schema,adaptor:this.adaptor})}async dequeue(e){let t=new m({schema:this.schema}),n=this.adaptor(e.databaseClient),r=await t.execute(n);if(r.resultType==="MESSAGE_DEQUEUED")return{resultType:"MESSAGE_DEQUEUED",message:new I({schema:this.schema,adaptor:this.adaptor,id:r.message.id,channelName:r.message.channelName,isUnlocked:r.message.isUnlocked,content:r.message.content,state:r.message.state,numAttempts:r.message.numAttempts})};else return r}channel(e){return new v({adaptor:this.adaptor,schema:this.schema,channelName:e})}batch(){return new D({schema:this.schema,adaptor:this.adaptor})}migrations(e={}){return[$,b,B,k,w,H,P,Q,W,V].sort((t,n)=>t.name.localeCompare(n.name)).flatMap((t)=>t.sql({schema:this.schema,eventChannel:e.eventChannel??null})).map((t)=>q(t.value))}}
|
package/dist/index.d.ts
CHANGED
|
@@ -62,7 +62,7 @@ export declare class MessageCreateCommand {
|
|
|
62
62
|
readonly createdAt: Date;
|
|
63
63
|
constructor(params: {
|
|
64
64
|
schema: string;
|
|
65
|
-
channelName
|
|
65
|
+
channelName?: string;
|
|
66
66
|
content: Buffer;
|
|
67
67
|
lockMs: number;
|
|
68
68
|
delayMs?: number;
|
|
@@ -159,11 +159,7 @@ export declare class MessageHeartbeatCommand {
|
|
|
159
159
|
});
|
|
160
160
|
execute(databaseClient: DatabaseClient): Promise<MessageHeartbeatCommandResult>;
|
|
161
161
|
}
|
|
162
|
-
export
|
|
163
|
-
messageId: string;
|
|
164
|
-
promise: Promise<void>;
|
|
165
|
-
};
|
|
166
|
-
export declare class QueueBatchChannelMessage {
|
|
162
|
+
export declare class QueueBatchChannelMessageModule {
|
|
167
163
|
private readonly schema;
|
|
168
164
|
private readonly channelName;
|
|
169
165
|
private readonly registerFn;
|
|
@@ -173,13 +169,14 @@ export declare class QueueBatchChannelMessage {
|
|
|
173
169
|
registerFn: BatchedCommandRegisterFn;
|
|
174
170
|
});
|
|
175
171
|
create(params: {
|
|
176
|
-
name?: string;
|
|
177
172
|
lockMs: number;
|
|
178
173
|
content: Buffer;
|
|
179
174
|
delayMs?: number;
|
|
180
|
-
}):
|
|
175
|
+
}): {
|
|
176
|
+
messageId: string;
|
|
177
|
+
};
|
|
181
178
|
}
|
|
182
|
-
export declare class
|
|
179
|
+
export declare class QueueBatchChannelPolicyModule {
|
|
183
180
|
private readonly schema;
|
|
184
181
|
private readonly channelName;
|
|
185
182
|
private readonly registerFn;
|
|
@@ -194,15 +191,31 @@ export declare class QueueBatchChannelPolicy {
|
|
|
194
191
|
}): void;
|
|
195
192
|
clear(): void;
|
|
196
193
|
}
|
|
197
|
-
export declare class
|
|
198
|
-
readonly policy:
|
|
199
|
-
readonly message:
|
|
194
|
+
export declare class QueueBatchChannelModule {
|
|
195
|
+
readonly policy: QueueBatchChannelPolicyModule;
|
|
196
|
+
readonly message: QueueBatchChannelMessageModule;
|
|
200
197
|
constructor(params: {
|
|
201
198
|
schema: string;
|
|
202
199
|
registerFn: BatchedCommandRegisterFn;
|
|
203
200
|
channelName: string;
|
|
204
201
|
});
|
|
205
202
|
}
|
|
203
|
+
export declare class QueueBatchMessageModule {
|
|
204
|
+
private readonly schema;
|
|
205
|
+
private readonly registerFn;
|
|
206
|
+
constructor(params: {
|
|
207
|
+
schema: string;
|
|
208
|
+
registerFn: BatchedCommandRegisterFn;
|
|
209
|
+
});
|
|
210
|
+
create(params: {
|
|
211
|
+
lockMs: number;
|
|
212
|
+
content: Buffer;
|
|
213
|
+
delayMs?: number;
|
|
214
|
+
}): {
|
|
215
|
+
messageId: string;
|
|
216
|
+
channelName: string;
|
|
217
|
+
};
|
|
218
|
+
}
|
|
206
219
|
export type BatchedCommand = {
|
|
207
220
|
sortKey: string;
|
|
208
221
|
execute: (databaseClient: DatabaseClient) => Promise<void>;
|
|
@@ -212,16 +225,17 @@ export declare class QueueBatch<T> {
|
|
|
212
225
|
private readonly commands;
|
|
213
226
|
private readonly schema;
|
|
214
227
|
private readonly adaptor;
|
|
228
|
+
readonly message: QueueBatchMessageModule;
|
|
215
229
|
constructor(params: {
|
|
216
230
|
schema: string;
|
|
217
231
|
adaptor: DatabaseClientAdaptor<T>;
|
|
218
232
|
});
|
|
219
|
-
channel(channelName: string):
|
|
233
|
+
channel(channelName: string): QueueBatchChannelModule;
|
|
220
234
|
execute(params: {
|
|
221
235
|
databaseClient: T;
|
|
222
236
|
}): Promise<void>;
|
|
223
237
|
}
|
|
224
|
-
export declare class
|
|
238
|
+
export declare class QueueChannelMessageModule<T> {
|
|
225
239
|
private readonly schema;
|
|
226
240
|
private readonly channelName;
|
|
227
241
|
private readonly adaptor;
|
|
@@ -232,13 +246,14 @@ export declare class QueueChannelMessage<T> {
|
|
|
232
246
|
});
|
|
233
247
|
create(params: {
|
|
234
248
|
databaseClient: T;
|
|
235
|
-
name?: string;
|
|
236
249
|
lockMs: number;
|
|
237
250
|
content: Buffer;
|
|
238
251
|
delayMs?: number;
|
|
239
|
-
}): Promise<
|
|
252
|
+
}): Promise<{
|
|
253
|
+
messageId: string;
|
|
254
|
+
}>;
|
|
240
255
|
}
|
|
241
|
-
export declare class
|
|
256
|
+
export declare class QueueChannelPolicyModule<T> {
|
|
242
257
|
private readonly schema;
|
|
243
258
|
private readonly adaptor;
|
|
244
259
|
private readonly channelName;
|
|
@@ -256,9 +271,9 @@ export declare class QueueChannelPolicy<T> {
|
|
|
256
271
|
databaseClient: T;
|
|
257
272
|
}): Promise<void>;
|
|
258
273
|
}
|
|
259
|
-
export declare class
|
|
260
|
-
readonly policy:
|
|
261
|
-
readonly message:
|
|
274
|
+
export declare class QueueChannelModule<T> {
|
|
275
|
+
readonly policy: QueueChannelPolicyModule<T>;
|
|
276
|
+
readonly message: QueueChannelMessageModule<T>;
|
|
262
277
|
constructor(params: {
|
|
263
278
|
schema: string;
|
|
264
279
|
adaptor: DatabaseClientAdaptor<T>;
|
|
@@ -296,6 +311,23 @@ export declare class QueueMessage<T> {
|
|
|
296
311
|
databaseClient: T;
|
|
297
312
|
}): Promise<MessageHeartbeatCommandResult>;
|
|
298
313
|
}
|
|
314
|
+
export declare class QueueMessageModule<T> {
|
|
315
|
+
private readonly schema;
|
|
316
|
+
private readonly adaptor;
|
|
317
|
+
constructor(params: {
|
|
318
|
+
schema: string;
|
|
319
|
+
adaptor: DatabaseClientAdaptor<T>;
|
|
320
|
+
});
|
|
321
|
+
create(params: {
|
|
322
|
+
databaseClient: T;
|
|
323
|
+
lockMs: number;
|
|
324
|
+
content: Buffer;
|
|
325
|
+
delayMs?: number;
|
|
326
|
+
}): Promise<{
|
|
327
|
+
messageId: string;
|
|
328
|
+
channelName: string;
|
|
329
|
+
}>;
|
|
330
|
+
}
|
|
299
331
|
export type MessageDequeueResult<T> = {
|
|
300
332
|
resultType: "MESSAGE_NOT_AVAILABLE";
|
|
301
333
|
retryMs: number | null;
|
|
@@ -313,11 +345,12 @@ export type QueueParams<T> = T extends DatabaseClient ? {
|
|
|
313
345
|
export declare class Queue<T = DatabaseClient> {
|
|
314
346
|
private readonly schema;
|
|
315
347
|
private readonly adaptor;
|
|
348
|
+
readonly message: QueueMessageModule<T>;
|
|
316
349
|
constructor(params: QueueParams<T>);
|
|
317
350
|
dequeue(params: {
|
|
318
351
|
databaseClient: T;
|
|
319
352
|
}): Promise<MessageDequeueResult<T>>;
|
|
320
|
-
channel(channelName: string):
|
|
353
|
+
channel(channelName: string): QueueChannelModule<T>;
|
|
321
354
|
batch(): QueueBatch<T>;
|
|
322
355
|
migrations(params?: {
|
|
323
356
|
eventChannel?: string;
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
var
|
|
1
|
+
var I=(e)=>{return e*1000};var m=I(0);var P=(e)=>{let t=JSON.parse(e);if(t.type===0)return{eventType:"MESSAGE_CREATED",id:t.id,delayMs:t.delay_ms};else if(t.type===1)return{eventType:"MESSAGE_DELETED",id:t.id};else if(t.type===2)return{eventType:"MESSAGE_DEFERRED",id:t.id,delayMs:t.delay_ms};else throw new Error("Unknown event type")};var r=(e)=>({nodeType:"VALUE",value:e}),s=(e)=>({nodeType:"REF",value:e}),Q=(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 new Error(`Unsupported value type: ${typeof e}`)},Y=(e)=>{return`"${e.replace(/"/g,'""')}"`},z=(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 new Error("Unsupported SQL node type")};var n=(e,...t)=>{let a=[];for(let _=0;_<e.length;_+=1)if(a.push(e[_]),_<t.length)a.push(z(t[_]));return Q(a.join(""))};class c{schema;channelName;createdAt;constructor(e){this.schema=e.schema,this.channelName=e.channelName,this.createdAt=new Date}async execute(e){await e.query(n`
|
|
2
2
|
SELECT 1 FROM ${s(this.schema)}."channel_policy_clear"(
|
|
3
3
|
$1
|
|
4
4
|
)
|
|
5
|
-
`.value,[this.channelName])}}class
|
|
5
|
+
`.value,[this.channelName])}}class l{schema;channelName;maxConcurrency;releaseIntervalMs;createdAt;constructor(e){this.schema=e.schema,this.channelName=e.channelName;let t=e.maxConcurrency??null;this.maxConcurrency=t!==null?Math.max(0,t):null;let a=e.releaseIntervalMs??null;this.releaseIntervalMs=a!==null?Math.max(0,a):null,this.createdAt=new Date}async execute(e){await e.query(n`
|
|
6
6
|
SELECT 1 FROM ${s(this.schema)}."channel_policy_set"(
|
|
7
7
|
$1,
|
|
8
8
|
$2::INTEGER,
|
|
9
9
|
$3::INTEGER
|
|
10
10
|
)
|
|
11
|
-
`.value,[this.channelName,this.maxConcurrency,this.releaseIntervalMs])}}import{randomUUID as
|
|
11
|
+
`.value,[this.channelName,this.maxConcurrency,this.releaseIntervalMs])}}import{randomBytes as J}from"crypto";var L=()=>{return J(16).toString("base64url")};import{randomUUID as X}from"node:crypto";class o{schema;channelName;content;lockMs;id;delayMs;createdAt;constructor(e){let t=Math.max(0,e.lockMs),a=e.delayMs===void 0?m:e.delayMs;this.id=X(),this.schema=e.schema,this.channelName=e.channelName??L(),this.content=e.content,this.lockMs=t,this.delayMs=a,this.createdAt=new Date}async execute(e){await e.query(n`
|
|
12
12
|
SELECT 1 FROM ${s(this.schema)}."message_create"(
|
|
13
13
|
$1,
|
|
14
14
|
$2,
|
|
@@ -40,9 +40,9 @@ var v=(e)=>{return e*1000};var m=v(0);var P=(e)=>{let t=JSON.parse(e);if(t.type=
|
|
|
40
40
|
$1,
|
|
41
41
|
$2::BIGINT
|
|
42
42
|
)
|
|
43
|
-
`.value,[this.id,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:"MESSAGE_STATE_INVALID"};else if(t.result_code===2)return{resultType:"MESSAGE_HEARTBEATED"};else throw new Error("Unexpected result")}}var
|
|
44
|
-
`),a=Number.MAX_SAFE_INTEGER;for(let _ of t){if(_.trim().length===0)continue;let
|
|
45
|
-
`).trim()};import{dirname as
|
|
43
|
+
`.value,[this.id,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:"MESSAGE_STATE_INVALID"};else if(t.result_code===2)return{resultType:"MESSAGE_HEARTBEATED"};else throw new Error("Unexpected result")}}var C=(e)=>{let t=e.split(`
|
|
44
|
+
`),a=Number.MAX_SAFE_INTEGER;for(let _ of t){if(_.trim().length===0)continue;let H=_.search(/\S/);a=Math.min(a,H)}return t.map((_)=>_.slice(a)).join(`
|
|
45
|
+
`).trim()};import{dirname as U}from"path";var __filename="/home/runner/work/lonnymq/lonnymq/src/core/path.ts",te=U(U(__filename)),se=new RegExp(`^${te}/`),E=(e)=>{return e.replace(se,"")};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/00-table-channel-policy.ts",O={name:E(__filename),sql:(e)=>{return[n`
|
|
46
46
|
CREATE TABLE ${s(e.schema)}."channel_policy" (
|
|
47
47
|
"id" UUID NOT NULL DEFAULT GEN_RANDOM_UUID(),
|
|
48
48
|
"name" TEXT NOT NULL,
|
|
@@ -54,7 +54,7 @@ var v=(e)=>{return e*1000};var m=v(0);var P=(e)=>{let t=JSON.parse(e);if(t.type=
|
|
|
54
54
|
`,n`
|
|
55
55
|
CREATE UNIQUE INDEX "channel_policy_name_ux"
|
|
56
56
|
ON ${s(e.schema)}."channel_policy" ("name");
|
|
57
|
-
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/01-table-channel-state.ts",
|
|
57
|
+
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/01-table-channel-state.ts",f={name:E(__filename),sql:(e)=>{return[n`
|
|
58
58
|
CREATE TABLE ${s(e.schema)}."channel_state" (
|
|
59
59
|
"id" UUID NOT NULL DEFAULT GEN_RANDOM_UUID(),
|
|
60
60
|
"name" TEXT NOT NULL,
|
|
@@ -79,7 +79,7 @@ var v=(e)=>{return e*1000};var m=v(0);var P=(e)=>{let t=JSON.parse(e);if(t.type=
|
|
|
79
79
|
"active_next_at" ASC
|
|
80
80
|
) WHERE "message_id" IS NOT NULL
|
|
81
81
|
AND ("max_concurrency" IS NULL OR "current_concurrency" < "max_concurrency");
|
|
82
|
-
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/02-table-message.ts",
|
|
82
|
+
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/02-table-message.ts",F={name:E(__filename),sql:(e)=>{return[n`
|
|
83
83
|
CREATE TABLE ${s(e.schema)}."message" (
|
|
84
84
|
"id" UUID NOT NULL,
|
|
85
85
|
"channel_name" TEXT NOT NULL,
|
|
@@ -106,7 +106,7 @@ var v=(e)=>{return e*1000};var m=v(0);var P=(e)=>{let t=JSON.parse(e);if(t.type=
|
|
|
106
106
|
ON ${s(e.schema)}."message" (
|
|
107
107
|
"unlock_at" ASC
|
|
108
108
|
) WHERE "is_locked";
|
|
109
|
-
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/03-function-message-create.ts",
|
|
109
|
+
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/03-function-message-create.ts",x={name:E(__filename),sql:(e)=>{return[n`
|
|
110
110
|
CREATE FUNCTION ${s(e.schema)}."message_create" (
|
|
111
111
|
p_id UUID,
|
|
112
112
|
p_channel_name TEXT,
|
|
@@ -217,7 +217,7 @@ var v=(e)=>{return e*1000};var m=v(0);var P=(e)=>{let t=JSON.parse(e);if(t.type=
|
|
|
217
217
|
END IF;
|
|
218
218
|
END;
|
|
219
219
|
$$ LANGUAGE plpgsql;
|
|
220
|
-
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/04-function-message-dequeue.ts",
|
|
220
|
+
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/04-function-message-dequeue.ts",ne=(e)=>n`
|
|
221
221
|
SELECT
|
|
222
222
|
"message"."id",
|
|
223
223
|
"message"."state",
|
|
@@ -230,7 +230,7 @@ var v=(e)=>{return e*1000};var m=v(0);var P=(e)=>{let t=JSON.parse(e);if(t.type=
|
|
|
230
230
|
WHERE "is_locked"
|
|
231
231
|
AND "unlock_at" <= ${e.now}
|
|
232
232
|
ORDER BY "unlock_at" ASC
|
|
233
|
-
`,
|
|
233
|
+
`,ae=(e)=>n`
|
|
234
234
|
SELECT
|
|
235
235
|
"channel_state"."id",
|
|
236
236
|
"channel_state"."name",
|
|
@@ -243,7 +243,7 @@ var v=(e)=>{return e*1000};var m=v(0);var P=(e)=>{let t=JSON.parse(e);if(t.type=
|
|
|
243
243
|
WHERE "message_id" IS NOT NULL
|
|
244
244
|
AND ("max_concurrency" IS NULL OR "current_concurrency" < "max_concurrency")
|
|
245
245
|
ORDER BY "active_next_at" ASC
|
|
246
|
-
`,
|
|
246
|
+
`,re=(e)=>n`
|
|
247
247
|
SELECT
|
|
248
248
|
"message"."id",
|
|
249
249
|
"message"."dequeue_at",
|
|
@@ -252,7 +252,7 @@ var v=(e)=>{return e*1000};var m=v(0);var P=(e)=>{let t=JSON.parse(e);if(t.type=
|
|
|
252
252
|
WHERE NOT "is_locked"
|
|
253
253
|
AND "channel_name" = ${e.channelName}
|
|
254
254
|
ORDER BY "dequeue_at" ASC, "seq_no" ASC
|
|
255
|
-
`,
|
|
255
|
+
`,G={name:E(__filename),sql:(e)=>{let t=ne({now:n`v_now`,schema:e.schema}),a=re({channelName:n`v_channel_state."name"`,schema:e.schema}),_=ae({schema:e.schema});return[n`
|
|
256
256
|
CREATE FUNCTION ${s(e.schema)}."message_dequeue" ()
|
|
257
257
|
RETURNS TABLE (
|
|
258
258
|
result_code INTEGER,
|
|
@@ -374,7 +374,7 @@ var v=(e)=>{return e*1000};var m=v(0);var P=(e)=>{let t=JSON.parse(e);if(t.type=
|
|
|
374
374
|
RETURN;
|
|
375
375
|
END;
|
|
376
376
|
$$ LANGUAGE plpgsql;
|
|
377
|
-
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/05-function-message-delete.ts",
|
|
377
|
+
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/05-function-message-delete.ts",q={name:E(__filename),sql:(e)=>{return[n`
|
|
378
378
|
CREATE FUNCTION ${s(e.schema)}."message_delete" (
|
|
379
379
|
p_id UUID,
|
|
380
380
|
p_num_attempts BIGINT
|
|
@@ -451,7 +451,7 @@ var v=(e)=>{return e*1000};var m=v(0);var P=(e)=>{let t=JSON.parse(e);if(t.type=
|
|
|
451
451
|
RETURN;
|
|
452
452
|
END;
|
|
453
453
|
$$ LANGUAGE plpgsql;
|
|
454
|
-
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/06-function-message-defer.ts"
|
|
454
|
+
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/06-function-message-defer.ts",$={name:E(__filename),sql:(e)=>{return[n`
|
|
455
455
|
CREATE FUNCTION ${s(e.schema)}."message_defer" (
|
|
456
456
|
p_id UUID,
|
|
457
457
|
p_num_attempts BIGINT,
|
|
@@ -547,7 +547,7 @@ var v=(e)=>{return e*1000};var m=v(0);var P=(e)=>{let t=JSON.parse(e);if(t.type=
|
|
|
547
547
|
RETURN;
|
|
548
548
|
END;
|
|
549
549
|
$$ LANGUAGE plpgsql;
|
|
550
|
-
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/07-function-message-heartbeat.ts",
|
|
550
|
+
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/07-function-message-heartbeat.ts",b={name:E(__filename),sql:(e)=>{return[n`
|
|
551
551
|
CREATE FUNCTION ${s(e.schema)}."message_heartbeat" (
|
|
552
552
|
p_id UUID,
|
|
553
553
|
p_num_attempts BIGINT
|
|
@@ -590,7 +590,7 @@ var v=(e)=>{return e*1000};var m=v(0);var P=(e)=>{let t=JSON.parse(e);if(t.type=
|
|
|
590
590
|
RETURN;
|
|
591
591
|
END;
|
|
592
592
|
$$ LANGUAGE plpgsql;
|
|
593
|
-
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/08-function-channel-policy-clear.ts"
|
|
593
|
+
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/08-function-channel-policy-clear.ts",B={name:E(__filename),sql:(e)=>{return[n`
|
|
594
594
|
CREATE FUNCTION ${s(e.schema)}."channel_policy_clear" (
|
|
595
595
|
p_name TEXT
|
|
596
596
|
) RETURNS VOID AS $$
|
|
@@ -619,7 +619,7 @@ var v=(e)=>{return e*1000};var m=v(0);var P=(e)=>{let t=JSON.parse(e);if(t.type=
|
|
|
619
619
|
END IF;
|
|
620
620
|
END;
|
|
621
621
|
$$ LANGUAGE plpgsql;
|
|
622
|
-
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/09-function-channel-policy-set.ts",
|
|
622
|
+
`]}};var __filename="/home/runner/work/lonnymq/lonnymq/src/migration/09-function-channel-policy-set.ts",k={name:E(__filename),sql:(e)=>{return[n`
|
|
623
623
|
CREATE FUNCTION ${s(e.schema)}."channel_policy_set" (
|
|
624
624
|
p_name TEXT,
|
|
625
625
|
p_max_concurrency INTEGER,
|
|
@@ -650,4 +650,4 @@ var v=(e)=>{return e*1000};var m=v(0);var P=(e)=>{let t=JSON.parse(e);if(t.type=
|
|
|
650
650
|
WHERE "name" = p_name;
|
|
651
651
|
END;
|
|
652
652
|
$$ LANGUAGE plpgsql;
|
|
653
|
-
`]}};class
|
|
653
|
+
`]}};class N{schema;channelName;registerFn;constructor(e){this.schema=e.schema,this.channelName=e.channelName,this.registerFn=e.registerFn}create(e){let t=new o({schema:this.schema,channelName:this.channelName,content:e.content,lockMs:e.lockMs,delayMs:e.delayMs});return this.registerFn({sortKey:JSON.stringify([t.channelName,t.createdAt.toISOString()]),execute:(a)=>t.execute(a)}),{messageId:t.id}}}class g{schema;channelName;registerFn;constructor(e){this.schema=e.schema,this.channelName=e.channelName,this.registerFn=e.registerFn}set(e){let t=new l({schema:this.schema,channelName:this.channelName,maxConcurrency:e.maxConcurrency,releaseIntervalMs:e.releaseIntervalMs});this.registerFn({sortKey:JSON.stringify([t.channelName,t.createdAt.toISOString()]),execute:async(a)=>{await t.execute(a)}})}clear(){let e=new c({schema:this.schema,channelName:this.channelName});this.registerFn({sortKey:JSON.stringify([e.channelName,e.createdAt.toISOString()]),execute:async(t)=>{await e.execute(t)}})}}class S{policy;message;constructor(e){this.message=new N(e),this.policy=new g(e)}}class R{schema;registerFn;constructor(e){this.schema=e.schema,this.registerFn=e.registerFn}create(e){let t=new o({schema:this.schema,content:e.content,lockMs:e.lockMs,delayMs:e.delayMs});return this.registerFn({sortKey:JSON.stringify([t.channelName,t.createdAt.toISOString()]),execute:(a)=>t.execute(a)}),{messageId:t.id,channelName:t.channelName}}}var _e=(e,t)=>{return e.sortKey.localeCompare(t.sortKey)};class A{commands;schema;adaptor;message;constructor(e){this.schema=e.schema,this.adaptor=e.adaptor,this.commands=[],this.message=new R({schema:this.schema,registerFn:(t)=>this.commands.push(t)})}channel(e){return new S({schema:this.schema,channelName:e,registerFn:(t)=>this.commands.push(t)})}async execute(e){let t=this.adaptor(e.databaseClient);for(let a of this.commands.sort(_e))await a.execute(t)}}class p{schema;channelName;adaptor;constructor(e){this.schema=e.schema,this.adaptor=e.adaptor,this.channelName=e.channelName}async create(e){let t=this.adaptor(e.databaseClient),a=new o({schema:this.schema,channelName:this.channelName,content:e.content,lockMs:e.lockMs,delayMs:e.delayMs});return await a.execute(t),{messageId:a.id}}}class D{schema;adaptor;channelName;constructor(e){this.schema=e.schema,this.adaptor=e.adaptor,this.channelName=e.channelName}set(e){let t=this.adaptor(e.databaseClient);return new l({schema:this.schema,channelName:this.channelName,maxConcurrency:e.maxConcurrency,releaseIntervalMs:e.releaseIntervalMs}).execute(t)}clear(e){let t=this.adaptor(e.databaseClient);return new c({schema:this.schema,channelName:this.channelName}).execute(t)}}class y{policy;message;constructor(e){this.message=new p({schema:e.schema,adaptor:e.adaptor,channelName:e.channelName}),this.policy=new D({schema:e.schema,adaptor:e.adaptor,channelName:e.channelName})}}class M{schema;adaptor;id;isUnlocked;channelName;content;state;numAttempts;constructor(e){this.schema=e.schema,this.adaptor=e.adaptor,this.id=e.id,this.channelName=e.channelName,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,delayMs:e.delayMs,state:e.state}).execute(t)}async delete(e){let t=this.adaptor(e.databaseClient);return new u({schema:this.schema,numAttempts:this.numAttempts,id:this.id}).execute(t)}async heartbeat(e){let t=this.adaptor(e.databaseClient);return new T({schema:this.schema,id:this.id,numAttempts:this.numAttempts}).execute(t)}}class v{schema;adaptor;constructor(e){this.schema=e.schema,this.adaptor=e.adaptor}async create(e){let t=this.adaptor(e.databaseClient),a=new o({schema:this.schema,content:e.content,lockMs:e.lockMs,delayMs:e.delayMs});return await a.execute(t),{messageId:a.id,channelName:a.channelName}}}class w{schema;adaptor;message;constructor(e){this.schema=e.schema,this.adaptor=e.adaptor?e.adaptor:(t)=>t,this.message=new v({schema:this.schema,adaptor:this.adaptor})}async dequeue(e){let t=new i({schema:this.schema}),a=this.adaptor(e.databaseClient),_=await t.execute(a);if(_.resultType==="MESSAGE_DEQUEUED")return{resultType:"MESSAGE_DEQUEUED",message:new M({schema:this.schema,adaptor:this.adaptor,id:_.message.id,channelName:_.message.channelName,isUnlocked:_.message.isUnlocked,content:_.message.content,state:_.message.state,numAttempts:_.message.numAttempts})};else return _}channel(e){return new y({adaptor:this.adaptor,schema:this.schema,channelName:e})}batch(){return new A({schema:this.schema,adaptor:this.adaptor})}migrations(e={}){return[O,f,F,x,G,q,$,b,k,B].sort((t,a)=>t.name.localeCompare(a.name)).flatMap((t)=>t.sql({schema:this.schema,eventChannel:e.eventChannel??null})).map((t)=>C(t.value))}}export{P as queueEventDecode,w as Queue,T as MessageHeartbeatCommand,i as MessageDequeueCommand,u as MessageDeleteCommand,d as MessageDeferCommand,o as MessageCreateCommand,l as ChannelPolicySetCommand,c as ChannelPolicyClearCommand};
|