@pgpm/jobs 0.4.0 → 0.5.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/Makefile CHANGED
@@ -1,5 +1,5 @@
1
1
  EXTENSION = launchql-jobs
2
- DATA = sql/launchql-jobs--0.4.6.sql
2
+ DATA = sql/launchql-jobs--0.4.0.sql
3
3
 
4
4
  PG_CONFIG = pg_config
5
5
  PGXS := $(shell $(PG_CONFIG) --pgxs)
package/README.md CHANGED
@@ -2,4 +2,371 @@
2
2
 
3
3
  Core job system for background task processing in PostgreSQL.
4
4
 
5
- Provides job queue management, task scheduling, and background processing capabilities for PostgreSQL applications.
5
+ ## Overview
6
+
7
+ `@pgpm/jobs` provides the core abstractions and interfaces for a PostgreSQL-based background job processing system. This package defines the schema, tables, and procedures for job queue management, scheduled jobs, and worker coordination. It serves as the foundation for building reliable background task processing systems entirely within PostgreSQL.
8
+
9
+ ## Features
10
+
11
+ - **Job Queue Schema**: Core `app_jobs` schema with jobs, scheduled_jobs, and job_queues tables
12
+ - **Job Management Procedures**: Functions for adding, retrieving, completing, and failing jobs
13
+ - **Scheduled Jobs**: Support for cron-style and rule-based job scheduling
14
+ - **Worker Coordination**: Job locking and worker management with expiry
15
+ - **Priority Queue**: Process jobs by priority, run time, and insertion order
16
+ - **Automatic Retries**: Configurable retry attempts with failure tracking
17
+ - **Job Keys**: Upsert semantics for idempotent job creation
18
+ - **Trigger Functions**: Automatic job creation from table changes
19
+
20
+ ## Installation
21
+
22
+ If you have `pgpm` installed:
23
+
24
+ ```bash
25
+ pgpm install @pgpm/jobs
26
+ pgpm deploy
27
+ ```
28
+
29
+ This is a quick way to get started. The sections below provide more detailed installation options.
30
+
31
+ ### Prerequisites
32
+
33
+ ```bash
34
+ # Install pgpm globally
35
+ npm install -g pgpm
36
+
37
+ # Start PostgreSQL
38
+ pgpm docker start
39
+
40
+ # Set environment variables
41
+ eval "$(pgpm env)"
42
+ ```
43
+
44
+ ### Deploy
45
+
46
+ #### Option 1: Deploy by installing with pgpm
47
+
48
+ ```bash
49
+ pgpm install @pgpm/jobs
50
+ pgpm deploy
51
+ ```
52
+
53
+ #### Option 2: Deploy from Package Directory
54
+
55
+ ```bash
56
+ cd packages/jobs/jobs
57
+ pgpm deploy --createdb
58
+ ```
59
+
60
+ #### Option 3: Deploy from Workspace Root
61
+
62
+ ```bash
63
+ # Install workspace dependencies
64
+ pgpm install
65
+
66
+ # Deploy with dependencies
67
+ pgpm deploy mydb1 --yes --createdb
68
+ ```
69
+
70
+ ## Core Schema
71
+
72
+ The `app_jobs` schema provides three main tables:
73
+
74
+ ### jobs Table
75
+ Stores active jobs awaiting processing:
76
+ - `id`: Unique job identifier
77
+ - `database_id`: Database/tenant identifier
78
+ - `task_identifier`: Job type/handler name
79
+ - `payload`: JSON data for the job
80
+ - `priority`: Lower numbers = higher priority
81
+ - `run_at`: Scheduled execution time
82
+ - `attempts`: Current attempt count
83
+ - `max_attempts`: Maximum retry attempts
84
+ - `locked_by`: Worker ID holding the lock
85
+ - `locked_at`: Lock timestamp
86
+ - `key`: Optional unique key for upsert
87
+
88
+ ### scheduled_jobs Table
89
+ Stores recurring job definitions:
90
+ - `id`: Unique identifier
91
+ - `database_id`: Database/tenant identifier
92
+ - `task_identifier`: Job type/handler name
93
+ - `payload`: JSON data template
94
+ - `schedule_info`: Cron or rule-based schedule
95
+ - `priority`: Job priority
96
+ - `max_attempts`: Maximum retries
97
+
98
+ ### job_queues Table
99
+ Tracks queue statistics and locking:
100
+ - `queue_name`: Queue identifier
101
+ - `job_count`: Number of jobs in queue
102
+ - `locked_by`: Worker ID holding queue lock
103
+ - `locked_at`: Lock timestamp
104
+
105
+ ## Usage
106
+
107
+ ### Adding Jobs
108
+
109
+ ```sql
110
+ -- Add a simple job
111
+ SELECT app_jobs.add_job(
112
+ db_id := '5b720132-17d5-424d-9bcb-ee7b17c13d43'::uuid,
113
+ identifier := 'send_email',
114
+ payload := '{"to": "user@example.com"}'::json
115
+ );
116
+
117
+ -- Add a delayed job with priority
118
+ SELECT app_jobs.add_job(
119
+ db_id := '5b720132-17d5-424d-9bcb-ee7b17c13d43'::uuid,
120
+ identifier := 'generate_report',
121
+ payload := '{"report_id": 123}'::json,
122
+ run_at := now() + interval '1 hour',
123
+ priority := 10
124
+ );
125
+ ```
126
+
127
+ ### Retrieving Jobs
128
+
129
+ ```sql
130
+ -- Worker fetches next job
131
+ SELECT * FROM app_jobs.get_job(
132
+ worker_id := 'worker-1',
133
+ task_identifiers := ARRAY['send_email', 'generate_report']
134
+ );
135
+ ```
136
+
137
+ ### Completing Jobs
138
+
139
+ ```sql
140
+ -- Mark job as successfully completed
141
+ SELECT app_jobs.complete_job(
142
+ worker_id := 'worker-1',
143
+ job_id := 123
144
+ );
145
+ ```
146
+
147
+ ### Failing Jobs
148
+
149
+ ```sql
150
+ -- Mark job as failed (will retry if attempts remain)
151
+ SELECT app_jobs.fail_job(
152
+ worker_id := 'worker-1',
153
+ job_id := 123,
154
+ error_message := 'Connection timeout'
155
+ );
156
+ ```
157
+
158
+ ### Scheduled Jobs
159
+
160
+ ```sql
161
+ -- Create a scheduled job
162
+ INSERT INTO app_jobs.scheduled_jobs (
163
+ database_id,
164
+ task_identifier,
165
+ schedule_info
166
+ ) VALUES (
167
+ '5b720132-17d5-424d-9bcb-ee7b17c13d43'::uuid,
168
+ 'cleanup_task',
169
+ '{"hour": [2], "minute": [0]}'::json
170
+ );
171
+
172
+ -- Execute a scheduled job
173
+ SELECT * FROM app_jobs.run_scheduled_job(1);
174
+ ```
175
+
176
+ ## Trigger Functions
177
+
178
+ The package includes trigger functions for automatic job creation:
179
+
180
+ ### tg_add_job_with_row_id
181
+ Creates a job when a row is inserted, using the row's ID in the payload.
182
+
183
+ ```sql
184
+ CREATE TRIGGER auto_process
185
+ AFTER INSERT ON my_table
186
+ FOR EACH ROW
187
+ EXECUTE FUNCTION app_jobs.tg_add_job_with_row_id(
188
+ 'database-uuid',
189
+ 'process_record',
190
+ 'id'
191
+ );
192
+ ```
193
+
194
+ ### tg_add_job_with_row
195
+ Creates a job with the entire row as JSON payload.
196
+
197
+ ```sql
198
+ CREATE TRIGGER auto_process
199
+ AFTER INSERT ON my_table
200
+ FOR EACH ROW
201
+ EXECUTE FUNCTION app_jobs.tg_add_job_with_row(
202
+ 'database-uuid',
203
+ 'process_record'
204
+ );
205
+ ```
206
+
207
+ ### tg_add_job_with_fields
208
+ Creates a job with specific fields from the row.
209
+
210
+ ```sql
211
+ CREATE TRIGGER auto_process
212
+ AFTER INSERT ON my_table
213
+ FOR EACH ROW
214
+ EXECUTE FUNCTION app_jobs.tg_add_job_with_fields(
215
+ 'database-uuid',
216
+ 'process_record',
217
+ 'field1',
218
+ 'field2',
219
+ 'field3'
220
+ );
221
+ ```
222
+
223
+ ## Functions Reference
224
+
225
+ ### app_jobs.add_job(...)
226
+ Adds a new job to the queue.
227
+
228
+ **Parameters:**
229
+ - `db_id` (uuid): Database identifier
230
+ - `identifier` (text): Job type
231
+ - `payload` (json): Job data
232
+ - `job_key` (text): Optional unique key
233
+ - `queue_name` (text): Optional queue name
234
+ - `run_at` (timestamptz): Execution time
235
+ - `max_attempts` (integer): Max retries
236
+ - `priority` (integer): Job priority
237
+
238
+ ### app_jobs.get_job(...)
239
+ Retrieves and locks the next available job.
240
+
241
+ **Parameters:**
242
+ - `worker_id` (text): Worker identifier
243
+ - `task_identifiers` (text[]): Job types to fetch
244
+ - `job_expiry` (interval): Lock expiry duration
245
+
246
+ ### app_jobs.complete_job(...)
247
+ Marks a job as completed.
248
+
249
+ **Parameters:**
250
+ - `worker_id` (text): Worker identifier
251
+ - `job_id` (bigint): Job identifier
252
+
253
+ ### app_jobs.fail_job(...)
254
+ Marks a job as failed.
255
+
256
+ **Parameters:**
257
+ - `worker_id` (text): Worker identifier
258
+ - `job_id` (bigint): Job identifier
259
+ - `error_message` (text): Error description
260
+
261
+ ### app_jobs.add_scheduled_job(...)
262
+ Creates a scheduled job.
263
+
264
+ **Parameters:**
265
+ - `db_id` (uuid): Database identifier
266
+ - `identifier` (text): Job type
267
+ - `payload` (json): Job data
268
+ - `schedule_info` (json): Schedule configuration
269
+ - Additional optional parameters
270
+
271
+ ### app_jobs.run_scheduled_job(...)
272
+ Executes a scheduled job.
273
+
274
+ **Parameters:**
275
+ - `scheduled_job_id` (bigint): Scheduled job identifier
276
+
277
+ ## Dependencies
278
+
279
+ - `@pgpm/default-roles`: Role-based access control
280
+ - `@pgpm/verify`: Verification utilities
281
+
282
+ ## Testing
283
+
284
+ ```bash
285
+ pnpm test
286
+ ```
287
+
288
+ ## Development
289
+
290
+ See the [Development](#development) section below for information on working with this package.
291
+
292
+ ---
293
+
294
+ ## Development
295
+
296
+ ### **Before You Begin**
297
+
298
+ ```bash
299
+ # 1. Install pgpm
300
+ npm install -g pgpm
301
+
302
+ # 2. Start Postgres (Docker or local)
303
+ pgpm docker start
304
+
305
+ # 3. Load PG* environment variables (PGHOST, PGUSER, ...)
306
+ eval "$(pgpm env)"
307
+ ```
308
+
309
+ ---
310
+
311
+ ### **Starting a New Project**
312
+
313
+ ```bash
314
+ # 1. Create a workspace
315
+ pgpm init --workspace
316
+ cd my-app
317
+
318
+ # 2. Create your first module
319
+ pgpm init
320
+
321
+ # 3. Add a migration
322
+ pgpm add some_change
323
+
324
+ # 4. Deploy (auto-creates database)
325
+ pgpm deploy --createdb
326
+ ```
327
+
328
+ ---
329
+
330
+ ### **Working With an Existing Project**
331
+
332
+ ```bash
333
+ # 1. Clone and enter the project
334
+ git clone <repo> && cd <project>
335
+
336
+ # 2. Install dependencies
337
+ pnpm install
338
+
339
+ # 3. Deploy locally
340
+ pgpm deploy --createdb
341
+ ```
342
+
343
+ ---
344
+
345
+ ### **Testing a Module Inside a Workspace**
346
+
347
+ ```bash
348
+ # 1. Install workspace deps
349
+ pnpm install
350
+
351
+ # 2. Enter the module directory
352
+ cd packages/<some-module>
353
+
354
+ # 3. Run tests in watch mode
355
+ pnpm test:watch
356
+ ```
357
+
358
+ ## Related Tooling
359
+
360
+ * [pgpm](https://github.com/launchql/launchql/tree/main/packages/pgpm): **🖥️ PostgreSQL Package Manager** for modular Postgres development. Works with database workspaces, scaffolding, migrations, seeding, and installing database packages.
361
+ * [pgsql-test](https://github.com/launchql/launchql/tree/main/packages/pgsql-test): **📊 Isolated testing environments** with per-test transaction rollbacks—ideal for integration tests, complex migrations, and RLS simulation.
362
+ * [supabase-test](https://github.com/launchql/launchql/tree/main/packages/supabase-test): **🧪 Supabase-native test harness** preconfigured for the local Supabase stack—per-test rollbacks, JWT/role context helpers, and CI/GitHub Actions ready.
363
+ * [graphile-test](https://github.com/launchql/launchql/tree/main/packages/graphile-test): **🔐 Authentication mocking** for Graphile-focused test helpers and emulating row-level security contexts.
364
+ * [pgsql-parser](https://github.com/launchql/pgsql-parser): **🔄 SQL conversion engine** that interprets and converts PostgreSQL syntax.
365
+ * [libpg-query-node](https://github.com/launchql/libpg-query-node): **🌉 Node.js bindings** for `libpg_query`, converting SQL into parse trees.
366
+ * [pg-proto-parser](https://github.com/launchql/pg-proto-parser): **📦 Protobuf parser** for parsing PostgreSQL Protocol Buffers definitions to generate TypeScript interfaces, utility functions, and JSON mappings for enums.
367
+
368
+ ## Disclaimer
369
+
370
+ AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED "AS IS", AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND.
371
+
372
+ No developer or entity involved in creating this software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the code, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value.
@@ -1,6 +1,6 @@
1
1
  # launchql-jobs extension
2
2
  comment = 'launchql-jobs extension'
3
- default_version = '0.4.6'
3
+ default_version = '0.4.0'
4
4
  module_pathname = '$libdir/launchql-jobs'
5
5
  requires = 'plpgsql,uuid-ossp,pgcrypto,launchql-default-roles,launchql-verify'
6
6
  relocatable = false
package/package.json CHANGED
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "name": "@pgpm/jobs",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Core job system for background task processing in PostgreSQL",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
8
8
  "scripts": {
9
- "bundle": "lql package",
9
+ "bundle": "pgpm package",
10
10
  "test": "jest",
11
11
  "test:watch": "jest --watch"
12
12
  },
13
13
  "dependencies": {
14
- "@pgpm/default-roles": "0.4.0",
15
- "@pgpm/verify": "0.4.0"
14
+ "@pgpm/default-roles": "0.5.0",
15
+ "@pgpm/verify": "0.5.0"
16
16
  },
17
17
  "devDependencies": {
18
- "@launchql/cli": "^4.9.0"
18
+ "pgpm": "^0.2.0"
19
19
  },
20
20
  "repository": {
21
21
  "type": "git",
@@ -25,5 +25,5 @@
25
25
  "bugs": {
26
26
  "url": "https://github.com/launchql/extensions/issues"
27
27
  },
28
- "gitHead": "cc9f52a335caa6e21ee7751b04b77c84ce6cb809"
28
+ "gitHead": "d8eedbb24ad22a106634bc3b919bfb8d41976c16"
29
29
  }