prisma-pgmq 0.1.0 → 1.0.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/README.md +83 -95
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,6 +24,25 @@ yarn add prisma-pgmq
|
|
|
24
24
|
- Prisma Client v5.0.0 or higher
|
|
25
25
|
- Node.js 16+
|
|
26
26
|
|
|
27
|
+
> **Enabling the PGMQ extension via Prisma**
|
|
28
|
+
>
|
|
29
|
+
> You can manage PostgreSQL extensions (including PGMQ) directly in your Prisma schema using the `postgresqlExtensions` preview feature. Add the extension to your `datasource` block in `schema.prisma`:
|
|
30
|
+
>
|
|
31
|
+
> ```prisma
|
|
32
|
+
> generator client {
|
|
33
|
+
> provider = "prisma-client-js"
|
|
34
|
+
> previewFeatures = ["postgresqlExtensions"]
|
|
35
|
+
> }
|
|
36
|
+
>
|
|
37
|
+
> datasource db {
|
|
38
|
+
> provider = "postgresql"
|
|
39
|
+
> url = env("DATABASE_URL")
|
|
40
|
+
> extensions = [pgmq]
|
|
41
|
+
> }
|
|
42
|
+
> ```
|
|
43
|
+
>
|
|
44
|
+
> For more details, see the [Prisma documentation on PostgreSQL extensions](https://www.prisma.io/docs/orm/prisma-schema/postgresql-extensions).
|
|
45
|
+
|
|
27
46
|
## Quick Start
|
|
28
47
|
|
|
29
48
|
### Functional API
|
|
@@ -35,18 +54,13 @@ import { pgmq } from 'prisma-pgmq';
|
|
|
35
54
|
const prisma = new PrismaClient();
|
|
36
55
|
|
|
37
56
|
// Create a queue
|
|
38
|
-
await prisma
|
|
39
|
-
await pgmq.createQueue(tx, 'my-work-queue');
|
|
40
|
-
});
|
|
57
|
+
await pgmq.createQueue(prisma, 'my-work-queue');
|
|
41
58
|
|
|
42
59
|
// Send a message
|
|
43
|
-
await prisma
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
email: 'user@example.com'
|
|
48
|
-
});
|
|
49
|
-
console.log('Message sent with ID:', msgId);
|
|
60
|
+
await pgmq.send(prisma, 'my-work-queue', {
|
|
61
|
+
userId: 123,
|
|
62
|
+
action: 'send-email',
|
|
63
|
+
email: 'user@example.com'
|
|
50
64
|
});
|
|
51
65
|
```
|
|
52
66
|
|
|
@@ -54,162 +68,161 @@ await prisma.$transaction(async (tx) => {
|
|
|
54
68
|
|
|
55
69
|
### Message Operations
|
|
56
70
|
|
|
57
|
-
#### `send(queueName, message, delay?)`
|
|
71
|
+
#### `send(tx, queueName, message, delay?)`
|
|
58
72
|
Send a single message to a queue.
|
|
59
73
|
|
|
60
74
|
```typescript
|
|
61
|
-
|
|
62
|
-
const msgId = await prisma.$pgmq.send('my-queue', { data: 'hello' });
|
|
75
|
+
const msgId = await pgmq.send(tx, 'my-queue', { data: 'hello' });
|
|
63
76
|
|
|
64
77
|
// Send with delay (seconds)
|
|
65
|
-
const msgId = await
|
|
78
|
+
const msgId = await pgmq.send(tx, 'my-queue', { data: 'hello' }, 30);
|
|
66
79
|
|
|
67
80
|
// Send with specific time
|
|
68
|
-
|
|
81
|
+
tx, 'my-queue', { data: 'hello' }, new Date('2024-01-01T10:00:00Z'));
|
|
69
82
|
```
|
|
70
83
|
|
|
71
|
-
#### `sendBatch(queueName, messages, delay?)`
|
|
84
|
+
#### `sendBatch(tx, queueName, messages, delay?)`
|
|
72
85
|
Send multiple messages to a queue in a single operation.
|
|
73
86
|
|
|
74
87
|
```typescript
|
|
75
|
-
const msgIds = await
|
|
88
|
+
const msgIds = await pgmq.sendBatch(tx, 'my-queue', [
|
|
76
89
|
{ id: 1, data: 'message 1' },
|
|
77
90
|
{ id: 2, data: 'message 2' },
|
|
78
91
|
{ id: 3, data: 'message 3' }
|
|
79
92
|
]);
|
|
80
93
|
```
|
|
81
94
|
|
|
82
|
-
#### `read(queueName, vt, qty?, conditional?)`
|
|
95
|
+
#### `read(tx, queueName, vt, qty?, conditional?)`
|
|
83
96
|
Read messages from a queue with visibility timeout.
|
|
84
97
|
|
|
85
98
|
```typescript
|
|
86
99
|
// Read up to 5 messages with 30 second visibility timeout
|
|
87
|
-
const messages = await
|
|
100
|
+
const messages = await pgmq.read(tx, 'my-queue', 30, 5);
|
|
88
101
|
|
|
89
102
|
// Read with conditional filtering
|
|
90
|
-
const messages = await
|
|
103
|
+
const messages = await pgmq.read(tx, 'my-queue', 30, 5, { priority: 'high' });
|
|
91
104
|
```
|
|
92
105
|
|
|
93
|
-
#### `readWithPoll(queueName, vt, qty?, maxPollSeconds?, pollIntervalMs?, conditional?)`
|
|
106
|
+
#### `readWithPoll(tx, queueName, vt, qty?, maxPollSeconds?, pollIntervalMs?, conditional?)`
|
|
94
107
|
Read messages with polling (wait for messages if none available).
|
|
95
108
|
|
|
96
109
|
```typescript
|
|
97
110
|
// Poll for up to 10 seconds, checking every 500ms
|
|
98
|
-
const messages = await
|
|
111
|
+
const messages = await pgmq.readWithPoll(tx, 'my-queue', 30, 1, 10, 500);
|
|
99
112
|
```
|
|
100
113
|
|
|
101
|
-
#### `pop(queueName)`
|
|
114
|
+
#### `pop(tx, queueName)`
|
|
102
115
|
Read and immediately delete a message (atomic operation).
|
|
103
116
|
|
|
104
117
|
```typescript
|
|
105
|
-
const messages = await
|
|
118
|
+
const messages = await pgmq.pop(tx, 'my-queue');
|
|
106
119
|
```
|
|
107
120
|
|
|
108
121
|
### Message Management
|
|
109
122
|
|
|
110
|
-
#### `deleteMessage(queueName, msgId)`
|
|
123
|
+
#### `deleteMessage(tx, queueName, msgId)`
|
|
111
124
|
Delete a specific message.
|
|
112
125
|
|
|
113
126
|
```typescript
|
|
114
|
-
const deleted = await
|
|
127
|
+
const deleted = await pgmq.deleteMessage(tx, 'my-queue', 123);
|
|
115
128
|
```
|
|
116
129
|
|
|
117
|
-
#### `deleteBatch(queueName, msgIds)`
|
|
130
|
+
#### `deleteBatch(tx, queueName, msgIds)`
|
|
118
131
|
Delete multiple messages.
|
|
119
132
|
|
|
120
133
|
```typescript
|
|
121
|
-
const deletedIds = await
|
|
134
|
+
const deletedIds = await pgmq.deleteBatch(tx, 'my-queue', [123, 124, 125]);
|
|
122
135
|
```
|
|
123
136
|
|
|
124
|
-
#### `archive(queueName, msgId)`
|
|
137
|
+
#### `archive(tx, queueName, msgId)`
|
|
125
138
|
Archive a message (move to archive table).
|
|
126
139
|
|
|
127
140
|
```typescript
|
|
128
|
-
const archived = await
|
|
141
|
+
const archived = await pgmq.archive(tx, 'my-queue', 123);
|
|
129
142
|
```
|
|
130
143
|
|
|
131
|
-
#### `archiveBatch(queueName, msgIds)`
|
|
144
|
+
#### `archiveBatch(tx, queueName, msgIds)`
|
|
132
145
|
Archive multiple messages.
|
|
133
146
|
|
|
134
147
|
```typescript
|
|
135
|
-
const archivedIds = await
|
|
148
|
+
const archivedIds = await pgmq.archiveBatch(tx, 'my-queue', [123, 124, 125]);
|
|
136
149
|
```
|
|
137
150
|
|
|
138
151
|
### Queue Management
|
|
139
152
|
|
|
140
|
-
#### `createQueue(queueName)`
|
|
153
|
+
#### `createQueue(tx, queueName)`
|
|
141
154
|
Create a new queue.
|
|
142
155
|
|
|
143
156
|
```typescript
|
|
144
|
-
await
|
|
157
|
+
await pgmq.createQueue(tx, 'my-new-queue');
|
|
145
158
|
```
|
|
146
159
|
|
|
147
|
-
#### `createPartitionedQueue(queueName, partitionInterval?, retentionInterval?)`
|
|
160
|
+
#### `createPartitionedQueue(tx, queueName, partitionInterval?, retentionInterval?)`
|
|
148
161
|
Create a partitioned queue for high-throughput scenarios.
|
|
149
162
|
|
|
150
163
|
```typescript
|
|
151
|
-
await
|
|
164
|
+
await pgmq.createPartitionedQueue(tx, 'high-volume-queue', '10000', '100000');
|
|
152
165
|
```
|
|
153
166
|
|
|
154
|
-
#### `createUnloggedQueue(queueName)`
|
|
167
|
+
#### `createUnloggedQueue(tx, queueName)`
|
|
155
168
|
Create an unlogged queue (better performance, less durability).
|
|
156
169
|
|
|
157
170
|
```typescript
|
|
158
|
-
await
|
|
171
|
+
await pgmq.createUnloggedQueue(tx, 'temp-queue');
|
|
159
172
|
```
|
|
160
173
|
|
|
161
|
-
#### `dropQueue(queueName)`
|
|
174
|
+
#### `dropQueue(tx, queueName)`
|
|
162
175
|
Delete a queue and all its messages.
|
|
163
176
|
|
|
164
177
|
```typescript
|
|
165
|
-
const dropped = await
|
|
178
|
+
const dropped = await pgmq.dropQueue(tx, 'old-queue');
|
|
166
179
|
```
|
|
167
180
|
|
|
168
|
-
#### `purgeQueue(queueName)`
|
|
181
|
+
#### `purgeQueue(tx, queueName)`
|
|
169
182
|
Remove all messages from a queue.
|
|
170
183
|
|
|
171
184
|
```typescript
|
|
172
|
-
const messageCount = await
|
|
185
|
+
const messageCount = await pgmq.purgeQueue(tx, 'my-queue');
|
|
173
186
|
```
|
|
174
187
|
|
|
175
188
|
### Utilities
|
|
176
189
|
|
|
177
|
-
#### `setVt(queueName, msgId, vtOffset)`
|
|
190
|
+
#### `setVt(tx, queueName, msgId, vtOffset)`
|
|
178
191
|
Set visibility timeout for a specific message.
|
|
179
192
|
|
|
180
193
|
```typescript
|
|
181
|
-
const message = await
|
|
194
|
+
const message = await pgmq.setVt(tx, 'my-queue', 123, 60); // 60 seconds
|
|
182
195
|
```
|
|
183
196
|
|
|
184
|
-
#### `listQueues()`
|
|
197
|
+
#### `listQueues(tx)`
|
|
185
198
|
Get information about all queues.
|
|
186
199
|
|
|
187
200
|
```typescript
|
|
188
|
-
const queues = await
|
|
201
|
+
const queues = await pgmq.listQueues(tx);
|
|
189
202
|
console.log(queues); // [{ queue_name: 'my-queue', created_at: ..., is_partitioned: false }]
|
|
190
203
|
```
|
|
191
204
|
|
|
192
|
-
#### `metrics(queueName)`
|
|
205
|
+
#### `metrics(tx, queueName)`
|
|
193
206
|
Get metrics for a specific queue.
|
|
194
207
|
|
|
195
208
|
```typescript
|
|
196
|
-
const metrics = await
|
|
209
|
+
const metrics = await pgmq.metrics(tx, 'my-queue');
|
|
197
210
|
console.log(metrics);
|
|
198
211
|
// {
|
|
199
212
|
// queue_name: 'my-queue',
|
|
200
|
-
// queue_length:
|
|
213
|
+
// queue_length: 5,
|
|
201
214
|
// newest_msg_age_sec: 10,
|
|
202
215
|
// oldest_msg_age_sec: 300,
|
|
203
|
-
// total_messages:
|
|
216
|
+
// total_messages: 1000,
|
|
204
217
|
// scrape_time: 2024-01-01T10:00:00.000Z
|
|
205
218
|
// }
|
|
206
219
|
```
|
|
207
220
|
|
|
208
|
-
#### `metricsAll()`
|
|
221
|
+
#### `metricsAll(tx)`
|
|
209
222
|
Get metrics for all queues.
|
|
210
223
|
|
|
211
224
|
```typescript
|
|
212
|
-
const allMetrics = await
|
|
225
|
+
const allMetrics = await pgmq.metricsAll(tx);
|
|
213
226
|
```
|
|
214
227
|
|
|
215
228
|
## Type Definitions
|
|
@@ -296,33 +309,27 @@ const prisma = new PrismaClient();
|
|
|
296
309
|
|
|
297
310
|
// Producer
|
|
298
311
|
async function sendTask(taskData: any) {
|
|
299
|
-
await prisma
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
timestamp: Date.now()
|
|
304
|
-
});
|
|
312
|
+
await pgmq.send(prisma, 'work-queue', {
|
|
313
|
+
type: 'process-user-data',
|
|
314
|
+
data: taskData,
|
|
315
|
+
timestamp: Date.now()
|
|
305
316
|
});
|
|
306
317
|
}
|
|
307
318
|
|
|
308
319
|
// Consumer
|
|
309
320
|
async function processMessages() {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
await pgmq.archive(tx, 'work-queue', message.msg_id);
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
});
|
|
321
|
+
const messages = await pgmq.readWithPoll(prisma, 'work-queue', 30, 5, 10, 1000);
|
|
322
|
+
for (const message of messages) {
|
|
323
|
+
try {
|
|
324
|
+
// Process the message
|
|
325
|
+
await handleTask(message.message);
|
|
326
|
+
// Delete on success
|
|
327
|
+
await pgmq.deleteMessage(prisma, 'work-queue', message.msg_id);
|
|
328
|
+
} catch (error) {
|
|
329
|
+
console.error('Task failed:', error);
|
|
330
|
+
// Archive failed messages for later analysis
|
|
331
|
+
await pgmq.archive(prisma, 'work-queue', message.msg_id);
|
|
332
|
+
}
|
|
326
333
|
}
|
|
327
334
|
}
|
|
328
335
|
|
|
@@ -338,32 +345,13 @@ async function handleTask(task: any) {
|
|
|
338
345
|
// Schedule a message for later processing
|
|
339
346
|
const futureDate = new Date(Date.now() + 24 * 60 * 60 * 1000); // 24 hours
|
|
340
347
|
|
|
341
|
-
await
|
|
348
|
+
await pgmq.send(prisma, 'scheduled-tasks', {
|
|
342
349
|
type: 'send-reminder',
|
|
343
350
|
userId: 123,
|
|
344
351
|
reminder: 'Your subscription expires tomorrow'
|
|
345
352
|
}, futureDate);
|
|
346
353
|
```
|
|
347
354
|
|
|
348
|
-
### Priority Queue Pattern
|
|
349
|
-
|
|
350
|
-
```typescript
|
|
351
|
-
// Send high-priority message
|
|
352
|
-
await prisma.$pgmq.send('tasks', {
|
|
353
|
-
priority: 'high',
|
|
354
|
-
type: 'urgent-processing',
|
|
355
|
-
data: urgentData
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
// Read high-priority messages first
|
|
359
|
-
const highPriorityMessages = await prisma.$pgmq.read('tasks', 30, 10, { priority: 'high' });
|
|
360
|
-
|
|
361
|
-
if (highPriorityMessages.length === 0) {
|
|
362
|
-
// Fall back to normal priority
|
|
363
|
-
const normalMessages = await prisma.$pgmq.read('tasks', 30, 10, { priority: 'normal' });
|
|
364
|
-
}
|
|
365
|
-
```
|
|
366
|
-
|
|
367
355
|
## Contributing
|
|
368
356
|
|
|
369
357
|
1. Fork the repository
|
|
@@ -376,7 +364,7 @@ if (highPriorityMessages.length === 0) {
|
|
|
376
364
|
|
|
377
365
|
```bash
|
|
378
366
|
# Clone the repository
|
|
379
|
-
git clone https://github.com/
|
|
367
|
+
git clone https://github.com/dvlkv/prisma-pgmq.git
|
|
380
368
|
cd prisma-pgmq
|
|
381
369
|
|
|
382
370
|
# Install dependencies
|