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.
Files changed (2) hide show
  1. package/README.md +83 -95
  2. 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.$transaction(async (tx) => {
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.$transaction(async (tx) => {
44
- const msgId = await pgmq.send(tx, 'my-work-queue', {
45
- userId: 123,
46
- action: 'send-email',
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
- // Send immediately
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 prisma.$pgmq.send('my-queue', { data: 'hello' }, 30);
78
+ const msgId = await pgmq.send(tx, 'my-queue', { data: 'hello' }, 30);
66
79
 
67
80
  // Send with specific time
68
- const msgId = await prisma.$pgmq.send('my-queue', { data: 'hello' }, new Date('2024-01-01T10:00:00Z'));
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 prisma.$pgmq.sendBatch('my-queue', [
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 prisma.$pgmq.read('my-queue', 30, 5);
100
+ const messages = await pgmq.read(tx, 'my-queue', 30, 5);
88
101
 
89
102
  // Read with conditional filtering
90
- const messages = await prisma.$pgmq.read('my-queue', 30, 5, { priority: 'high' });
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 prisma.$pgmq.readWithPoll('my-queue', 30, 1, 10, 500);
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 prisma.$pgmq.pop('my-queue');
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 prisma.$pgmq.deleteMessage('my-queue', 123);
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 prisma.$pgmq.deleteBatch('my-queue', [123, 124, 125]);
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 prisma.$pgmq.archive('my-queue', 123);
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 prisma.$pgmq.archiveBatch('my-queue', [123, 124, 125]);
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 prisma.$pgmq.createQueue('my-new-queue');
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 prisma.$pgmq.createPartitionedQueue('high-volume-queue', '10000', '100000');
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 prisma.$pgmq.createUnloggedQueue('temp-queue');
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 prisma.$pgmq.dropQueue('old-queue');
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 prisma.$pgmq.purgeQueue('my-queue');
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 prisma.$pgmq.setVt('my-queue', 123, 60); // 60 seconds
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 prisma.$pgmq.listQueues();
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 prisma.$pgmq.metrics('my-queue');
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: 5n,
213
+ // queue_length: 5,
201
214
  // newest_msg_age_sec: 10,
202
215
  // oldest_msg_age_sec: 300,
203
- // total_messages: 1000n,
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 prisma.$pgmq.metricsAll();
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.$transaction(async (tx) => {
300
- await pgmq.send(tx, 'work-queue', {
301
- type: 'process-user-data',
302
- data: taskData,
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
- while (true) {
311
- await prisma.$transaction(async (tx) => {
312
- const messages = await pgmq.readWithPoll(tx, 'work-queue', 30, 5, 10, 1000);
313
- for (const message of messages) {
314
- try {
315
- // Process the message
316
- await handleTask(message.message);
317
- // Delete on success
318
- await pgmq.deleteMessage(tx, 'work-queue', message.msg_id);
319
- } catch (error) {
320
- console.error('Task failed:', error);
321
- // Archive failed messages for later analysis
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 prisma.$pgmq.send('scheduled-tasks', {
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/your-username/prisma-pgmq.git
367
+ git clone https://github.com/dvlkv/prisma-pgmq.git
380
368
  cd prisma-pgmq
381
369
 
382
370
  # Install dependencies
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prisma-pgmq",
3
- "version": "0.1.0",
3
+ "version": "1.0.0",
4
4
  "description": "A Prisma PGMQ implementation providing type-safe message queue operations",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",