queuerPy 0.15.0__tar.gz → 0.17.0__tar.gz
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.
- {queuerpy-0.15.0/queuerPy.egg-info → queuerpy-0.17.0}/PKG-INFO +82 -7
- {queuerpy-0.15.0 → queuerpy-0.17.0}/README.md +81 -6
- {queuerpy-0.15.0 → queuerpy-0.17.0}/_version.py +1 -1
- {queuerpy-0.15.0 → queuerpy-0.17.0}/database/db_job.py +13 -5
- {queuerpy-0.15.0 → queuerpy-0.17.0}/model/batch_job.py +4 -3
- {queuerpy-0.15.0 → queuerpy-0.17.0}/model/job.py +16 -1
- {queuerpy-0.15.0 → queuerpy-0.17.0}/pyproject.toml +2 -2
- {queuerpy-0.15.0 → queuerpy-0.17.0/queuerPy.egg-info}/PKG-INFO +82 -7
- {queuerpy-0.15.0 → queuerpy-0.17.0}/queuer_job.py +25 -9
- {queuerpy-0.15.0 → queuerpy-0.17.0}/sql/job.sql +102 -16
- {queuerpy-0.15.0 → queuerpy-0.17.0}/sql/worker.sql +17 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/LICENSE +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/MANIFEST.in +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/__init__.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/core/__init__.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/core/broadcaster.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/core/listener.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/core/retryer.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/core/runner.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/core/scheduler.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/core/ticker.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/database/__init__.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/database/db_listener.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/database/db_master.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/database/db_worker.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/helper/__init__.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/helper/database.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/helper/error.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/helper/logging.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/helper/sql.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/helper/task.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/model/__init__.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/model/connection.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/model/master.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/model/options.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/model/options_on_error.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/model/task.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/model/worker.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/py.typed +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/queuer.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/queuerPy.egg-info/SOURCES.txt +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/queuerPy.egg-info/dependency_links.txt +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/queuerPy.egg-info/requires.txt +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/queuerPy.egg-info/top_level.txt +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/queuer_global.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/queuer_listener.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/queuer_master.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/queuer_next_interval.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/queuer_task.py +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/setup.cfg +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/sql/master.sql +0 -0
- {queuerpy-0.15.0 → queuerpy-0.17.0}/sql/notify.sql +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: queuerPy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.17.0
|
|
4
4
|
Summary: A Python implementation of the queuer system - a job queuing and processing system with PostgreSQL backend
|
|
5
5
|
Author-email: Simon Herrmann <siherrmann@users.noreply.github.com>
|
|
6
6
|
Maintainer-email: Simon Herrmann <siherrmann@users.noreply.github.com>
|
|
@@ -43,9 +43,10 @@ Dynamic: license-file
|
|
|
43
43
|
|
|
44
44
|
# queuerPy
|
|
45
45
|
|
|
46
|
+
[](https://pypi.org/project/queuerPy/)
|
|
46
47
|
[](https://www.python.org/)
|
|
47
|
-
[](https://github.com/siherrmann/queuer/blob/master/LICENSE)
|
|
48
48
|

|
|
49
|
+
[](https://github.com/siherrmann/queuer/blob/master/LICENSE)
|
|
49
50
|
|
|
50
51
|
Python port of the queuer package - a queueing system based on PostgreSQL.
|
|
51
52
|
|
|
@@ -97,9 +98,15 @@ def example_task():
|
|
|
97
98
|
That's easy, right? Adding a job is just as easy:
|
|
98
99
|
|
|
99
100
|
```python
|
|
100
|
-
# Add a job to the queue
|
|
101
|
+
# Add a job to the queue with positional arguments
|
|
101
102
|
job = q.add_job(example_task, 5, "12")
|
|
102
103
|
print(f"Job added: {job.rid}")
|
|
104
|
+
|
|
105
|
+
# Add a job with keyword arguments (kwargs)
|
|
106
|
+
job = q.add_job(example_task, paramKeyed1="test", debug=True)
|
|
107
|
+
|
|
108
|
+
# Add a job with both positional and keyword arguments
|
|
109
|
+
job = q.add_job(example_task, 5, "12", paramKeyed1="test", debug=True)
|
|
103
110
|
```
|
|
104
111
|
|
|
105
112
|
In the initialisation of the queuer the existence of the necessary database tables is checked and if they don't exist they get created. The database is configured with these environment variables:
|
|
@@ -199,6 +206,72 @@ This method handles the registration of a task, making the worker able to pick u
|
|
|
199
206
|
|
|
200
207
|
---
|
|
201
208
|
|
|
209
|
+
## add_job
|
|
210
|
+
|
|
211
|
+
The `add_job` method adds a new job to the queue for execution. Jobs are units of work that will be processed by the queuer.
|
|
212
|
+
|
|
213
|
+
```python
|
|
214
|
+
def add_job(
|
|
215
|
+
self,
|
|
216
|
+
task: Union[Callable, str],
|
|
217
|
+
*parameters: Any,
|
|
218
|
+
**parameters_keyed: Any
|
|
219
|
+
) -> Job
|
|
220
|
+
|
|
221
|
+
def add_job_with_options(
|
|
222
|
+
self,
|
|
223
|
+
options: Optional[Options],
|
|
224
|
+
task: Union[Callable, str],
|
|
225
|
+
*parameters: Any,
|
|
226
|
+
**parameters_keyed: Any
|
|
227
|
+
) -> Job
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
- `task`: A `Callable` or `str` representing the task to execute. If a callable, it must be registered with `add_task` first.
|
|
231
|
+
- `options`: Optional `Options` for custom error handling or scheduling behavior. Only available in `add_job_with_options()`.
|
|
232
|
+
- `*parameters`: Positional arguments to pass to the task function.
|
|
233
|
+
- `**parameters_keyed`: Keyword arguments to pass to the task function (Python-specific feature).
|
|
234
|
+
|
|
235
|
+
**Examples:**
|
|
236
|
+
|
|
237
|
+
```python
|
|
238
|
+
# Job with both positional and keyword arguments
|
|
239
|
+
job = queuer.add_job(my_task, "arg1", paramKeyed1="test", paramKeyed2=1)
|
|
240
|
+
|
|
241
|
+
# Job with custom options (requires add_job_with_options)
|
|
242
|
+
options = Options(on_error=OnError(max_retries=5))
|
|
243
|
+
job = queuer.add_job_with_options(options, my_task, "arg1", debug=True)
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**Note:** Keyword arguments (`**parameters_keyed`) are stored separately in the database and enable Python functions to be called with named parameters. This is useful for optional parameters, default values, and improved code clarity. Go jobs continue to use only positional parameters.
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## add_jobs
|
|
251
|
+
|
|
252
|
+
The `add_jobs` method allows efficient batch insertion of multiple jobs at once.
|
|
253
|
+
|
|
254
|
+
```python
|
|
255
|
+
def add_jobs(self, batch_jobs: List[BatchJob]) -> List[UUID]
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
- `batch_jobs`: A list of `BatchJob` instances to insert.
|
|
259
|
+
|
|
260
|
+
**Example:**
|
|
261
|
+
|
|
262
|
+
```python
|
|
263
|
+
from model.batch_job import BatchJob
|
|
264
|
+
|
|
265
|
+
batch = [
|
|
266
|
+
BatchJob(task=my_task, parameters=[1, "a"]),
|
|
267
|
+
BatchJob(task=my_task, parameters=[2], parameters_keyed={"name": "b"}),
|
|
268
|
+
BatchJob(task=my_task, parameters_keyed={"id": 3, "name": "c"})
|
|
269
|
+
]
|
|
270
|
+
job_rids = queuer.add_jobs(batch)
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
202
275
|
## add_next_interval_func
|
|
203
276
|
|
|
204
277
|
The `add_next_interval_func` method registers a custom function that determines the next execution time for scheduled jobs. This is useful for implementing complex scheduling logic beyond simple fixed intervals.
|
|
@@ -296,19 +369,20 @@ class Schedule:
|
|
|
296
369
|
### Job Management
|
|
297
370
|
|
|
298
371
|
```python
|
|
299
|
-
# Add a
|
|
300
|
-
job = queuer.add_job(my_task, param1, param2)
|
|
372
|
+
# Add a job with both positional and keyword arguments
|
|
373
|
+
job = queuer.add_job(my_task, param1, param2, paramKeyed1="test", paramKeyed2=1)
|
|
301
374
|
|
|
302
375
|
# Add a job with custom options
|
|
303
376
|
from model.options import Options, OnError
|
|
304
377
|
options = Options(on_error=OnError(max_retries=5, timeout=60.0))
|
|
305
|
-
job = queuer.add_job_with_options(options, my_task, param1)
|
|
378
|
+
job = queuer.add_job_with_options(options, my_task, param1, paramKeyed1="test")
|
|
306
379
|
|
|
307
380
|
# Add multiple jobs as a batch
|
|
308
381
|
from model.batch_job import BatchJob
|
|
309
382
|
batch = [
|
|
310
383
|
BatchJob(task=my_task, parameters=[1, "a"]),
|
|
311
|
-
BatchJob(task=my_task, parameters=[2, "b"
|
|
384
|
+
BatchJob(task=my_task, parameters=[2], parameters_keyed={"name": "b"}),
|
|
385
|
+
BatchJob(task=my_task, parameters_keyed={"id": 3, "name": "c"})
|
|
312
386
|
]
|
|
313
387
|
queuer.add_jobs(batch)
|
|
314
388
|
|
|
@@ -335,6 +409,7 @@ worker_jobs = queuer.get_jobs_by_worker_rid(worker.rid)
|
|
|
335
409
|
|
|
336
410
|
# ⭐ Features
|
|
337
411
|
|
|
412
|
+
- **Keyword Arguments Support**: Python functions can use both positional arguments (`*args`) and keyword arguments (`**kwargs`), while maintaining compatibility with Go jobs that use only positional parameters.
|
|
338
413
|
- **Async/Await Support**: Full asyncio integration with threading fallbacks.
|
|
339
414
|
- **PostgreSQL NOTIFY/LISTEN**: Real-time job notifications without polling overhead.
|
|
340
415
|
- **Batch Job Processing**: Insert job batches efficiently using PostgreSQL's `COPY FROM` feature.
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# queuerPy
|
|
2
2
|
|
|
3
|
+
[](https://pypi.org/project/queuerPy/)
|
|
3
4
|
[](https://www.python.org/)
|
|
4
|
-
[](https://github.com/siherrmann/queuer/blob/master/LICENSE)
|
|
5
5
|

|
|
6
|
+
[](https://github.com/siherrmann/queuer/blob/master/LICENSE)
|
|
6
7
|
|
|
7
8
|
Python port of the queuer package - a queueing system based on PostgreSQL.
|
|
8
9
|
|
|
@@ -54,9 +55,15 @@ def example_task():
|
|
|
54
55
|
That's easy, right? Adding a job is just as easy:
|
|
55
56
|
|
|
56
57
|
```python
|
|
57
|
-
# Add a job to the queue
|
|
58
|
+
# Add a job to the queue with positional arguments
|
|
58
59
|
job = q.add_job(example_task, 5, "12")
|
|
59
60
|
print(f"Job added: {job.rid}")
|
|
61
|
+
|
|
62
|
+
# Add a job with keyword arguments (kwargs)
|
|
63
|
+
job = q.add_job(example_task, paramKeyed1="test", debug=True)
|
|
64
|
+
|
|
65
|
+
# Add a job with both positional and keyword arguments
|
|
66
|
+
job = q.add_job(example_task, 5, "12", paramKeyed1="test", debug=True)
|
|
60
67
|
```
|
|
61
68
|
|
|
62
69
|
In the initialisation of the queuer the existence of the necessary database tables is checked and if they don't exist they get created. The database is configured with these environment variables:
|
|
@@ -156,6 +163,72 @@ This method handles the registration of a task, making the worker able to pick u
|
|
|
156
163
|
|
|
157
164
|
---
|
|
158
165
|
|
|
166
|
+
## add_job
|
|
167
|
+
|
|
168
|
+
The `add_job` method adds a new job to the queue for execution. Jobs are units of work that will be processed by the queuer.
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
def add_job(
|
|
172
|
+
self,
|
|
173
|
+
task: Union[Callable, str],
|
|
174
|
+
*parameters: Any,
|
|
175
|
+
**parameters_keyed: Any
|
|
176
|
+
) -> Job
|
|
177
|
+
|
|
178
|
+
def add_job_with_options(
|
|
179
|
+
self,
|
|
180
|
+
options: Optional[Options],
|
|
181
|
+
task: Union[Callable, str],
|
|
182
|
+
*parameters: Any,
|
|
183
|
+
**parameters_keyed: Any
|
|
184
|
+
) -> Job
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
- `task`: A `Callable` or `str` representing the task to execute. If a callable, it must be registered with `add_task` first.
|
|
188
|
+
- `options`: Optional `Options` for custom error handling or scheduling behavior. Only available in `add_job_with_options()`.
|
|
189
|
+
- `*parameters`: Positional arguments to pass to the task function.
|
|
190
|
+
- `**parameters_keyed`: Keyword arguments to pass to the task function (Python-specific feature).
|
|
191
|
+
|
|
192
|
+
**Examples:**
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
# Job with both positional and keyword arguments
|
|
196
|
+
job = queuer.add_job(my_task, "arg1", paramKeyed1="test", paramKeyed2=1)
|
|
197
|
+
|
|
198
|
+
# Job with custom options (requires add_job_with_options)
|
|
199
|
+
options = Options(on_error=OnError(max_retries=5))
|
|
200
|
+
job = queuer.add_job_with_options(options, my_task, "arg1", debug=True)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**Note:** Keyword arguments (`**parameters_keyed`) are stored separately in the database and enable Python functions to be called with named parameters. This is useful for optional parameters, default values, and improved code clarity. Go jobs continue to use only positional parameters.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## add_jobs
|
|
208
|
+
|
|
209
|
+
The `add_jobs` method allows efficient batch insertion of multiple jobs at once.
|
|
210
|
+
|
|
211
|
+
```python
|
|
212
|
+
def add_jobs(self, batch_jobs: List[BatchJob]) -> List[UUID]
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
- `batch_jobs`: A list of `BatchJob` instances to insert.
|
|
216
|
+
|
|
217
|
+
**Example:**
|
|
218
|
+
|
|
219
|
+
```python
|
|
220
|
+
from model.batch_job import BatchJob
|
|
221
|
+
|
|
222
|
+
batch = [
|
|
223
|
+
BatchJob(task=my_task, parameters=[1, "a"]),
|
|
224
|
+
BatchJob(task=my_task, parameters=[2], parameters_keyed={"name": "b"}),
|
|
225
|
+
BatchJob(task=my_task, parameters_keyed={"id": 3, "name": "c"})
|
|
226
|
+
]
|
|
227
|
+
job_rids = queuer.add_jobs(batch)
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
159
232
|
## add_next_interval_func
|
|
160
233
|
|
|
161
234
|
The `add_next_interval_func` method registers a custom function that determines the next execution time for scheduled jobs. This is useful for implementing complex scheduling logic beyond simple fixed intervals.
|
|
@@ -253,19 +326,20 @@ class Schedule:
|
|
|
253
326
|
### Job Management
|
|
254
327
|
|
|
255
328
|
```python
|
|
256
|
-
# Add a
|
|
257
|
-
job = queuer.add_job(my_task, param1, param2)
|
|
329
|
+
# Add a job with both positional and keyword arguments
|
|
330
|
+
job = queuer.add_job(my_task, param1, param2, paramKeyed1="test", paramKeyed2=1)
|
|
258
331
|
|
|
259
332
|
# Add a job with custom options
|
|
260
333
|
from model.options import Options, OnError
|
|
261
334
|
options = Options(on_error=OnError(max_retries=5, timeout=60.0))
|
|
262
|
-
job = queuer.add_job_with_options(options, my_task, param1)
|
|
335
|
+
job = queuer.add_job_with_options(options, my_task, param1, paramKeyed1="test")
|
|
263
336
|
|
|
264
337
|
# Add multiple jobs as a batch
|
|
265
338
|
from model.batch_job import BatchJob
|
|
266
339
|
batch = [
|
|
267
340
|
BatchJob(task=my_task, parameters=[1, "a"]),
|
|
268
|
-
BatchJob(task=my_task, parameters=[2, "b"
|
|
341
|
+
BatchJob(task=my_task, parameters=[2], parameters_keyed={"name": "b"}),
|
|
342
|
+
BatchJob(task=my_task, parameters_keyed={"id": 3, "name": "c"})
|
|
269
343
|
]
|
|
270
344
|
queuer.add_jobs(batch)
|
|
271
345
|
|
|
@@ -292,6 +366,7 @@ worker_jobs = queuer.get_jobs_by_worker_rid(worker.rid)
|
|
|
292
366
|
|
|
293
367
|
# ⭐ Features
|
|
294
368
|
|
|
369
|
+
- **Keyword Arguments Support**: Python functions can use both positional arguments (`*args`) and keyword arguments (`**kwargs`), while maintaining compatibility with Go jobs that use only positional parameters.
|
|
295
370
|
- **Async/Await Support**: Full asyncio integration with threading fallbacks.
|
|
296
371
|
- **PostgreSQL NOTIFY/LISTEN**: Real-time job notifications without polling overhead.
|
|
297
372
|
- **Batch Job Processing**: Insert job batches efficiently using PostgreSQL's `COPY FROM` feature.
|
|
@@ -95,11 +95,12 @@ class JobDBHandler:
|
|
|
95
95
|
|
|
96
96
|
with self.db.instance.cursor(row_factory=dict_row) as cur:
|
|
97
97
|
cur.execute(
|
|
98
|
-
"SELECT * FROM insert_job(%s, %s, %s, %s, %s, %s);",
|
|
98
|
+
"SELECT * FROM insert_job(%s, %s, %s, %s, %s, %s, %s);",
|
|
99
99
|
(
|
|
100
100
|
json.dumps(job.options.to_dict()) if job.options else None,
|
|
101
101
|
job.task_name,
|
|
102
102
|
json.dumps(job.parameters),
|
|
103
|
+
json.dumps(job.parameters_keyed),
|
|
103
104
|
job.status,
|
|
104
105
|
job.scheduled_at,
|
|
105
106
|
job.schedule_count,
|
|
@@ -144,21 +145,28 @@ class JobDBHandler:
|
|
|
144
145
|
raise ValueError("Database connection is not established")
|
|
145
146
|
|
|
146
147
|
try:
|
|
147
|
-
batch_data: List[Tuple[str, str, str, Optional[datetime]]] = []
|
|
148
|
+
batch_data: List[Tuple[str, str, str, str, Optional[datetime]]] = []
|
|
148
149
|
for job in jobs:
|
|
149
150
|
options_json = (
|
|
150
151
|
json.dumps(job.options.to_dict()) if job.options else "{}"
|
|
151
152
|
)
|
|
152
153
|
parameters_json = json.dumps(job.parameters)
|
|
154
|
+
parameters_keyed_json = json.dumps(job.parameters_keyed)
|
|
153
155
|
batch_data.append(
|
|
154
|
-
(
|
|
156
|
+
(
|
|
157
|
+
options_json,
|
|
158
|
+
job.task_name,
|
|
159
|
+
parameters_json,
|
|
160
|
+
parameters_keyed_json,
|
|
161
|
+
job.scheduled_at,
|
|
162
|
+
)
|
|
155
163
|
)
|
|
156
164
|
|
|
157
165
|
with self.db.instance.cursor(row_factory=dict_row) as cur:
|
|
158
166
|
cur.executemany(
|
|
159
167
|
"""
|
|
160
|
-
INSERT INTO job (options, task_name, parameters, scheduled_at)
|
|
161
|
-
VALUES (%s, %s, %s, %s)
|
|
168
|
+
INSERT INTO job (options, task_name, parameters, parameters_keyed, scheduled_at)
|
|
169
|
+
VALUES (%s, %s, %s, %s, %s)
|
|
162
170
|
""",
|
|
163
171
|
batch_data,
|
|
164
172
|
)
|
|
@@ -3,8 +3,8 @@ BatchJob model for Python queuer implementation.
|
|
|
3
3
|
Mirrors Go's model.BatchJob struct.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
from typing import Any, List, Optional, Union, Callable
|
|
7
|
-
from dataclasses import dataclass
|
|
6
|
+
from typing import Any, Dict, List, Optional, Union, Callable
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
8
|
|
|
9
9
|
from .options import Options
|
|
10
10
|
|
|
@@ -16,5 +16,6 @@ class BatchJob:
|
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
18
|
task: Union[Callable[..., Any], str]
|
|
19
|
-
parameters: List[Any]
|
|
19
|
+
parameters: List[Any] = field(default_factory=list)
|
|
20
|
+
parameters_keyed: Dict[str, Any] = field(default_factory=dict)
|
|
20
21
|
options: Optional[Options] = None
|
|
@@ -40,7 +40,8 @@ class Job:
|
|
|
40
40
|
|
|
41
41
|
# Job definition
|
|
42
42
|
task_name: str = ""
|
|
43
|
-
parameters: List[Any] = field(default_factory=
|
|
43
|
+
parameters: List[Any] = field(default_factory=list)
|
|
44
|
+
parameters_keyed: Dict[str, Any] = field(default_factory=dict)
|
|
44
45
|
options: Optional[Options] = None
|
|
45
46
|
|
|
46
47
|
# Job state
|
|
@@ -65,6 +66,7 @@ class Job:
|
|
|
65
66
|
"worker_rid": str(self.worker_rid),
|
|
66
67
|
"task_name": self.task_name,
|
|
67
68
|
"parameters": self.parameters,
|
|
69
|
+
"parameters_keyed": self.parameters_keyed,
|
|
68
70
|
"options": self.options.to_dict() if self.options else None,
|
|
69
71
|
"status": self.status,
|
|
70
72
|
"scheduled_at": (
|
|
@@ -110,6 +112,7 @@ class Job:
|
|
|
110
112
|
job.worker_rid = UUID(data["worker_rid"])
|
|
111
113
|
job.task_name = data.get("task_name", "")
|
|
112
114
|
job.parameters = data.get("parameters", [])
|
|
115
|
+
job.parameters_keyed = data.get("parameters_keyed", {})
|
|
113
116
|
if data.get("options"):
|
|
114
117
|
job.options = Options.from_dict(data["options"])
|
|
115
118
|
job.status = data.get("status", JobStatus.QUEUED)
|
|
@@ -173,6 +176,16 @@ class Job:
|
|
|
173
176
|
else parameters_value
|
|
174
177
|
)
|
|
175
178
|
|
|
179
|
+
parameters_keyed_value = row.get(
|
|
180
|
+
"output_parameters_keyed", row.get("parameters_keyed")
|
|
181
|
+
)
|
|
182
|
+
if parameters_keyed_value:
|
|
183
|
+
job.parameters_keyed = (
|
|
184
|
+
json.loads(parameters_keyed_value)
|
|
185
|
+
if isinstance(parameters_keyed_value, str)
|
|
186
|
+
else parameters_keyed_value
|
|
187
|
+
)
|
|
188
|
+
|
|
176
189
|
results_value = row.get("output_results", row.get("results"))
|
|
177
190
|
if results_value is not None:
|
|
178
191
|
# JSONB columns return Python objects directly, no JSON parsing needed
|
|
@@ -194,6 +207,7 @@ def new_job(
|
|
|
194
207
|
task: Union[Callable[..., Any], str],
|
|
195
208
|
options: Optional[Options] = None,
|
|
196
209
|
*parameters: Any,
|
|
210
|
+
**parameters_keyed: Any,
|
|
197
211
|
) -> Job:
|
|
198
212
|
"""
|
|
199
213
|
Create a new job from a task function or task name.
|
|
@@ -237,6 +251,7 @@ def new_job(
|
|
|
237
251
|
job: Job = Job()
|
|
238
252
|
job.task_name = task_name
|
|
239
253
|
job.parameters = list(parameters)
|
|
254
|
+
job.parameters_keyed = parameters_keyed
|
|
240
255
|
job.options = options
|
|
241
256
|
job.status = status
|
|
242
257
|
job.scheduled_at = scheduled_at
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "queuerPy"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.17.0"
|
|
8
8
|
description = "A Python implementation of the queuer system - a job queuing and processing system with PostgreSQL backend"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
|
@@ -92,7 +92,7 @@ pythonVersion = "3.8"
|
|
|
92
92
|
pythonPlatform = "All"
|
|
93
93
|
|
|
94
94
|
[tool.mypy]
|
|
95
|
-
python_version = "0.
|
|
95
|
+
python_version = "0.17.0"
|
|
96
96
|
warn_return_any = true
|
|
97
97
|
warn_unused_configs = true
|
|
98
98
|
disallow_untyped_defs = true
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: queuerPy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.17.0
|
|
4
4
|
Summary: A Python implementation of the queuer system - a job queuing and processing system with PostgreSQL backend
|
|
5
5
|
Author-email: Simon Herrmann <siherrmann@users.noreply.github.com>
|
|
6
6
|
Maintainer-email: Simon Herrmann <siherrmann@users.noreply.github.com>
|
|
@@ -43,9 +43,10 @@ Dynamic: license-file
|
|
|
43
43
|
|
|
44
44
|
# queuerPy
|
|
45
45
|
|
|
46
|
+
[](https://pypi.org/project/queuerPy/)
|
|
46
47
|
[](https://www.python.org/)
|
|
47
|
-
[](https://github.com/siherrmann/queuer/blob/master/LICENSE)
|
|
48
48
|

|
|
49
|
+
[](https://github.com/siherrmann/queuer/blob/master/LICENSE)
|
|
49
50
|
|
|
50
51
|
Python port of the queuer package - a queueing system based on PostgreSQL.
|
|
51
52
|
|
|
@@ -97,9 +98,15 @@ def example_task():
|
|
|
97
98
|
That's easy, right? Adding a job is just as easy:
|
|
98
99
|
|
|
99
100
|
```python
|
|
100
|
-
# Add a job to the queue
|
|
101
|
+
# Add a job to the queue with positional arguments
|
|
101
102
|
job = q.add_job(example_task, 5, "12")
|
|
102
103
|
print(f"Job added: {job.rid}")
|
|
104
|
+
|
|
105
|
+
# Add a job with keyword arguments (kwargs)
|
|
106
|
+
job = q.add_job(example_task, paramKeyed1="test", debug=True)
|
|
107
|
+
|
|
108
|
+
# Add a job with both positional and keyword arguments
|
|
109
|
+
job = q.add_job(example_task, 5, "12", paramKeyed1="test", debug=True)
|
|
103
110
|
```
|
|
104
111
|
|
|
105
112
|
In the initialisation of the queuer the existence of the necessary database tables is checked and if they don't exist they get created. The database is configured with these environment variables:
|
|
@@ -199,6 +206,72 @@ This method handles the registration of a task, making the worker able to pick u
|
|
|
199
206
|
|
|
200
207
|
---
|
|
201
208
|
|
|
209
|
+
## add_job
|
|
210
|
+
|
|
211
|
+
The `add_job` method adds a new job to the queue for execution. Jobs are units of work that will be processed by the queuer.
|
|
212
|
+
|
|
213
|
+
```python
|
|
214
|
+
def add_job(
|
|
215
|
+
self,
|
|
216
|
+
task: Union[Callable, str],
|
|
217
|
+
*parameters: Any,
|
|
218
|
+
**parameters_keyed: Any
|
|
219
|
+
) -> Job
|
|
220
|
+
|
|
221
|
+
def add_job_with_options(
|
|
222
|
+
self,
|
|
223
|
+
options: Optional[Options],
|
|
224
|
+
task: Union[Callable, str],
|
|
225
|
+
*parameters: Any,
|
|
226
|
+
**parameters_keyed: Any
|
|
227
|
+
) -> Job
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
- `task`: A `Callable` or `str` representing the task to execute. If a callable, it must be registered with `add_task` first.
|
|
231
|
+
- `options`: Optional `Options` for custom error handling or scheduling behavior. Only available in `add_job_with_options()`.
|
|
232
|
+
- `*parameters`: Positional arguments to pass to the task function.
|
|
233
|
+
- `**parameters_keyed`: Keyword arguments to pass to the task function (Python-specific feature).
|
|
234
|
+
|
|
235
|
+
**Examples:**
|
|
236
|
+
|
|
237
|
+
```python
|
|
238
|
+
# Job with both positional and keyword arguments
|
|
239
|
+
job = queuer.add_job(my_task, "arg1", paramKeyed1="test", paramKeyed2=1)
|
|
240
|
+
|
|
241
|
+
# Job with custom options (requires add_job_with_options)
|
|
242
|
+
options = Options(on_error=OnError(max_retries=5))
|
|
243
|
+
job = queuer.add_job_with_options(options, my_task, "arg1", debug=True)
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**Note:** Keyword arguments (`**parameters_keyed`) are stored separately in the database and enable Python functions to be called with named parameters. This is useful for optional parameters, default values, and improved code clarity. Go jobs continue to use only positional parameters.
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## add_jobs
|
|
251
|
+
|
|
252
|
+
The `add_jobs` method allows efficient batch insertion of multiple jobs at once.
|
|
253
|
+
|
|
254
|
+
```python
|
|
255
|
+
def add_jobs(self, batch_jobs: List[BatchJob]) -> List[UUID]
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
- `batch_jobs`: A list of `BatchJob` instances to insert.
|
|
259
|
+
|
|
260
|
+
**Example:**
|
|
261
|
+
|
|
262
|
+
```python
|
|
263
|
+
from model.batch_job import BatchJob
|
|
264
|
+
|
|
265
|
+
batch = [
|
|
266
|
+
BatchJob(task=my_task, parameters=[1, "a"]),
|
|
267
|
+
BatchJob(task=my_task, parameters=[2], parameters_keyed={"name": "b"}),
|
|
268
|
+
BatchJob(task=my_task, parameters_keyed={"id": 3, "name": "c"})
|
|
269
|
+
]
|
|
270
|
+
job_rids = queuer.add_jobs(batch)
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
202
275
|
## add_next_interval_func
|
|
203
276
|
|
|
204
277
|
The `add_next_interval_func` method registers a custom function that determines the next execution time for scheduled jobs. This is useful for implementing complex scheduling logic beyond simple fixed intervals.
|
|
@@ -296,19 +369,20 @@ class Schedule:
|
|
|
296
369
|
### Job Management
|
|
297
370
|
|
|
298
371
|
```python
|
|
299
|
-
# Add a
|
|
300
|
-
job = queuer.add_job(my_task, param1, param2)
|
|
372
|
+
# Add a job with both positional and keyword arguments
|
|
373
|
+
job = queuer.add_job(my_task, param1, param2, paramKeyed1="test", paramKeyed2=1)
|
|
301
374
|
|
|
302
375
|
# Add a job with custom options
|
|
303
376
|
from model.options import Options, OnError
|
|
304
377
|
options = Options(on_error=OnError(max_retries=5, timeout=60.0))
|
|
305
|
-
job = queuer.add_job_with_options(options, my_task, param1)
|
|
378
|
+
job = queuer.add_job_with_options(options, my_task, param1, paramKeyed1="test")
|
|
306
379
|
|
|
307
380
|
# Add multiple jobs as a batch
|
|
308
381
|
from model.batch_job import BatchJob
|
|
309
382
|
batch = [
|
|
310
383
|
BatchJob(task=my_task, parameters=[1, "a"]),
|
|
311
|
-
BatchJob(task=my_task, parameters=[2, "b"
|
|
384
|
+
BatchJob(task=my_task, parameters=[2], parameters_keyed={"name": "b"}),
|
|
385
|
+
BatchJob(task=my_task, parameters_keyed={"id": 3, "name": "c"})
|
|
312
386
|
]
|
|
313
387
|
queuer.add_jobs(batch)
|
|
314
388
|
|
|
@@ -335,6 +409,7 @@ worker_jobs = queuer.get_jobs_by_worker_rid(worker.rid)
|
|
|
335
409
|
|
|
336
410
|
# ⭐ Features
|
|
337
411
|
|
|
412
|
+
- **Keyword Arguments Support**: Python functions can use both positional arguments (`*args`) and keyword arguments (`**kwargs`), while maintaining compatibility with Go jobs that use only positional parameters.
|
|
338
413
|
- **Async/Await Support**: Full asyncio integration with threading fallbacks.
|
|
339
414
|
- **PostgreSQL NOTIFY/LISTEN**: Real-time job notifications without polling overhead.
|
|
340
415
|
- **Batch Job Processing**: Insert job batches efficiently using PostgreSQL's `COPY FROM` feature.
|
|
@@ -34,17 +34,23 @@ class QueuerJobMixin(QueuerGlobalMixin):
|
|
|
34
34
|
def __init__(self):
|
|
35
35
|
super().__init__()
|
|
36
36
|
|
|
37
|
-
def add_job(
|
|
37
|
+
def add_job(
|
|
38
|
+
self,
|
|
39
|
+
task: Union[Callable[..., Any], str],
|
|
40
|
+
*parameters: Any,
|
|
41
|
+
**parameters_keyed: Any,
|
|
42
|
+
) -> Job:
|
|
38
43
|
"""
|
|
39
44
|
Add a job to the queue with the given task and parameters.
|
|
40
45
|
|
|
41
46
|
:param task: Either a function or a string with the task name
|
|
42
|
-
:param parameters:
|
|
47
|
+
:param parameters: Positional parameters to pass to the task
|
|
48
|
+
:param parameters_keyed: Keyword parameters to pass to the task
|
|
43
49
|
:returns: The created job
|
|
44
50
|
:raises Exception: If something goes wrong
|
|
45
51
|
"""
|
|
46
52
|
options: Optional[Options] = self._merge_options(None)
|
|
47
|
-
job: Job = self._add_job(task, options, *parameters)
|
|
53
|
+
job: Job = self._add_job(task, options, *parameters, **parameters_keyed)
|
|
48
54
|
|
|
49
55
|
logger.info(f"Job added: {job.rid}")
|
|
50
56
|
|
|
@@ -55,6 +61,7 @@ class QueuerJobMixin(QueuerGlobalMixin):
|
|
|
55
61
|
options: Optional[Options],
|
|
56
62
|
task: Union[Callable[..., Any], str],
|
|
57
63
|
*parameters: Any,
|
|
64
|
+
**parameters_keyed: Any,
|
|
58
65
|
) -> Job:
|
|
59
66
|
"""Add a new job with specific options."""
|
|
60
67
|
# Merge default options with provided options
|
|
@@ -62,7 +69,9 @@ class QueuerJobMixin(QueuerGlobalMixin):
|
|
|
62
69
|
|
|
63
70
|
try:
|
|
64
71
|
# Create new job
|
|
65
|
-
new_job: Job = create_job(
|
|
72
|
+
new_job: Job = create_job(
|
|
73
|
+
task, options_merged, *parameters, **parameters_keyed
|
|
74
|
+
)
|
|
66
75
|
job: Job = self.db_job.insert_job(new_job)
|
|
67
76
|
|
|
68
77
|
logger.info(f"Job with options added: {job.rid}")
|
|
@@ -82,7 +91,9 @@ class QueuerJobMixin(QueuerGlobalMixin):
|
|
|
82
91
|
for batch_job in batch_jobs:
|
|
83
92
|
options: Optional[Options] = self._merge_options(batch_job.options)
|
|
84
93
|
task_name: str = get_task_name_from_interface(batch_job.task)
|
|
85
|
-
job: Job = create_job(
|
|
94
|
+
job: Job = create_job(
|
|
95
|
+
task_name, options, *batch_job.parameters, **batch_job.parameters_keyed
|
|
96
|
+
)
|
|
86
97
|
jobs.append(job)
|
|
87
98
|
|
|
88
99
|
self.db_job.batch_insert_jobs(jobs)
|
|
@@ -232,7 +243,9 @@ class QueuerJobMixin(QueuerGlobalMixin):
|
|
|
232
243
|
raise Exception(f"Job not found in archive: {job_rid}")
|
|
233
244
|
|
|
234
245
|
# Readd the job to the queue
|
|
235
|
-
new_job = self.add_job_with_options(
|
|
246
|
+
new_job = self.add_job_with_options(
|
|
247
|
+
job.options, job.task_name, *job.parameters, **job.parameters_keyed
|
|
248
|
+
)
|
|
236
249
|
logger.info(f"Job readded: {new_job.rid}")
|
|
237
250
|
return new_job
|
|
238
251
|
|
|
@@ -317,18 +330,20 @@ class QueuerJobMixin(QueuerGlobalMixin):
|
|
|
317
330
|
task: Union[Callable[..., Any], str],
|
|
318
331
|
options: Optional["Options"],
|
|
319
332
|
*parameters: Any,
|
|
333
|
+
**parameters_keyed: Any,
|
|
320
334
|
) -> Job:
|
|
321
335
|
"""
|
|
322
336
|
Add a job to the queue with all necessary parameters.
|
|
323
337
|
|
|
324
338
|
:param task: Either a function or a string with the task name
|
|
325
339
|
:param options: Job-specific options (can be None)
|
|
326
|
-
:param parameters:
|
|
340
|
+
:param parameters: Positional parameters to pass to the task
|
|
341
|
+
:param parameters_keyed: Keyword parameters to pass to the task
|
|
327
342
|
:returns: The created job
|
|
328
343
|
:raises Exception: If something goes wrong
|
|
329
344
|
"""
|
|
330
345
|
try:
|
|
331
|
-
new_job = create_job(task, options, *parameters)
|
|
346
|
+
new_job = create_job(task, options, *parameters, **parameters_keyed)
|
|
332
347
|
job = self.db_job.insert_job(new_job)
|
|
333
348
|
|
|
334
349
|
return job
|
|
@@ -405,7 +420,8 @@ class QueuerJobMixin(QueuerGlobalMixin):
|
|
|
405
420
|
|
|
406
421
|
try:
|
|
407
422
|
parameters = getattr(job, "parameters", [])
|
|
408
|
-
|
|
423
|
+
parameters_keyed = getattr(job, "parameters_keyed", {})
|
|
424
|
+
runner = Runner(task, *parameters, **parameters_keyed)
|
|
409
425
|
|
|
410
426
|
logger.info(f"Created runner for job {job.rid}")
|
|
411
427
|
|
|
@@ -15,6 +15,9 @@ BEGIN
|
|
|
15
15
|
options JSONB DEFAULT '{}',
|
|
16
16
|
task_name VARCHAR(100) DEFAULT '',
|
|
17
17
|
parameters JSONB DEFAULT '[]',
|
|
18
|
+
parameters_encrypted BYTEA DEFAULT '',
|
|
19
|
+
parameters_keyed JSONB DEFAULT '{}',
|
|
20
|
+
parameters_keyed_encrypted BYTEA DEFAULT '',
|
|
18
21
|
status VARCHAR(50) DEFAULT 'QUEUED',
|
|
19
22
|
scheduled_at TIMESTAMP DEFAULT NULL,
|
|
20
23
|
started_at TIMESTAMP DEFAULT NULL,
|
|
@@ -62,6 +65,7 @@ CREATE OR REPLACE FUNCTION insert_job(
|
|
|
62
65
|
input_options JSONB,
|
|
63
66
|
input_task_name VARCHAR(100),
|
|
64
67
|
input_parameters JSONB,
|
|
68
|
+
input_parameters_keyed JSONB,
|
|
65
69
|
input_status VARCHAR(50),
|
|
66
70
|
input_scheduled_at TIMESTAMP,
|
|
67
71
|
input_schedule_count INT
|
|
@@ -74,6 +78,7 @@ RETURNS TABLE (
|
|
|
74
78
|
output_options JSONB,
|
|
75
79
|
output_task_name VARCHAR(100),
|
|
76
80
|
output_parameters JSONB,
|
|
81
|
+
output_parameters_keyed JSONB,
|
|
77
82
|
output_status VARCHAR(50),
|
|
78
83
|
output_scheduled_at TIMESTAMP,
|
|
79
84
|
output_schedule_count INT,
|
|
@@ -84,8 +89,8 @@ RETURNS TABLE (
|
|
|
84
89
|
AS $$
|
|
85
90
|
BEGIN
|
|
86
91
|
RETURN QUERY
|
|
87
|
-
INSERT INTO job (options, task_name, parameters, status, scheduled_at, schedule_count)
|
|
88
|
-
VALUES (input_options, input_task_name, input_parameters, input_status, input_scheduled_at, input_schedule_count)
|
|
92
|
+
INSERT INTO job (options, task_name, parameters, parameters_keyed, status, scheduled_at, schedule_count)
|
|
93
|
+
VALUES (input_options, input_task_name, input_parameters, input_parameters_keyed, input_status, input_scheduled_at, input_schedule_count)
|
|
89
94
|
RETURNING
|
|
90
95
|
job.id,
|
|
91
96
|
job.rid,
|
|
@@ -94,6 +99,7 @@ BEGIN
|
|
|
94
99
|
job.options,
|
|
95
100
|
job.task_name,
|
|
96
101
|
job.parameters,
|
|
102
|
+
job.parameters_keyed,
|
|
97
103
|
job.status,
|
|
98
104
|
job.scheduled_at,
|
|
99
105
|
job.schedule_count,
|
|
@@ -112,6 +118,7 @@ RETURNS TABLE (
|
|
|
112
118
|
output_options JSONB,
|
|
113
119
|
output_task_name VARCHAR(100),
|
|
114
120
|
output_parameters JSONB,
|
|
121
|
+
output_parameters_keyed JSONB,
|
|
115
122
|
output_status VARCHAR(50),
|
|
116
123
|
output_scheduled_at TIMESTAMP,
|
|
117
124
|
output_started_at TIMESTAMP,
|
|
@@ -182,6 +189,7 @@ BEGIN
|
|
|
182
189
|
job.options,
|
|
183
190
|
job.task_name,
|
|
184
191
|
job.parameters,
|
|
192
|
+
job.parameters_keyed,
|
|
185
193
|
job.status,
|
|
186
194
|
job.scheduled_at,
|
|
187
195
|
job.started_at,
|
|
@@ -206,6 +214,7 @@ RETURNS TABLE (
|
|
|
206
214
|
output_options JSONB,
|
|
207
215
|
output_task_name VARCHAR(100),
|
|
208
216
|
output_parameters JSONB,
|
|
217
|
+
output_parameters_keyed JSONB,
|
|
209
218
|
output_status VARCHAR(50),
|
|
210
219
|
output_scheduled_at TIMESTAMP,
|
|
211
220
|
output_started_at TIMESTAMP,
|
|
@@ -229,6 +238,9 @@ BEGIN
|
|
|
229
238
|
options,
|
|
230
239
|
task_name,
|
|
231
240
|
parameters,
|
|
241
|
+
parameters_encrypted,
|
|
242
|
+
parameters_keyed,
|
|
243
|
+
parameters_keyed_encrypted,
|
|
232
244
|
scheduled_at,
|
|
233
245
|
started_at,
|
|
234
246
|
schedule_count,
|
|
@@ -244,6 +256,9 @@ BEGIN
|
|
|
244
256
|
options,
|
|
245
257
|
task_name,
|
|
246
258
|
parameters,
|
|
259
|
+
parameters_encrypted,
|
|
260
|
+
parameters_keyed,
|
|
261
|
+
parameters_keyed_encrypted,
|
|
247
262
|
status,
|
|
248
263
|
scheduled_at,
|
|
249
264
|
started_at,
|
|
@@ -262,6 +277,9 @@ BEGIN
|
|
|
262
277
|
jobs_old.options,
|
|
263
278
|
jobs_old.task_name,
|
|
264
279
|
jobs_old.parameters,
|
|
280
|
+
jobs_old.parameters_encrypted,
|
|
281
|
+
jobs_old.parameters_keyed,
|
|
282
|
+
jobs_old.parameters_keyed_encrypted,
|
|
265
283
|
input_status,
|
|
266
284
|
jobs_old.scheduled_at,
|
|
267
285
|
jobs_old.started_at,
|
|
@@ -280,6 +298,7 @@ BEGIN
|
|
|
280
298
|
options,
|
|
281
299
|
task_name,
|
|
282
300
|
parameters,
|
|
301
|
+
parameters_keyed,
|
|
283
302
|
status,
|
|
284
303
|
scheduled_at,
|
|
285
304
|
started_at,
|
|
@@ -307,6 +326,7 @@ RETURNS TABLE (
|
|
|
307
326
|
output_options JSONB,
|
|
308
327
|
output_task_name VARCHAR(100),
|
|
309
328
|
output_parameters JSONB,
|
|
329
|
+
output_parameters_keyed JSONB,
|
|
310
330
|
output_status VARCHAR(50),
|
|
311
331
|
output_scheduled_at TIMESTAMP,
|
|
312
332
|
output_started_at TIMESTAMP,
|
|
@@ -330,6 +350,9 @@ BEGIN
|
|
|
330
350
|
options,
|
|
331
351
|
task_name,
|
|
332
352
|
parameters,
|
|
353
|
+
parameters_encrypted,
|
|
354
|
+
parameters_keyed,
|
|
355
|
+
parameters_keyed_encrypted,
|
|
333
356
|
scheduled_at,
|
|
334
357
|
started_at,
|
|
335
358
|
schedule_count,
|
|
@@ -345,6 +368,9 @@ BEGIN
|
|
|
345
368
|
options,
|
|
346
369
|
task_name,
|
|
347
370
|
parameters,
|
|
371
|
+
parameters_encrypted,
|
|
372
|
+
parameters_keyed,
|
|
373
|
+
parameters_keyed_encrypted,
|
|
348
374
|
status,
|
|
349
375
|
scheduled_at,
|
|
350
376
|
started_at,
|
|
@@ -363,6 +389,9 @@ BEGIN
|
|
|
363
389
|
jobs_old.options,
|
|
364
390
|
jobs_old.task_name,
|
|
365
391
|
jobs_old.parameters,
|
|
392
|
+
jobs_old.parameters_encrypted,
|
|
393
|
+
jobs_old.parameters_keyed,
|
|
394
|
+
jobs_old.parameters_keyed_encrypted,
|
|
366
395
|
input_status,
|
|
367
396
|
jobs_old.scheduled_at,
|
|
368
397
|
jobs_old.started_at,
|
|
@@ -381,6 +410,7 @@ BEGIN
|
|
|
381
410
|
options,
|
|
382
411
|
task_name,
|
|
383
412
|
parameters,
|
|
413
|
+
parameters_keyed,
|
|
384
414
|
status,
|
|
385
415
|
scheduled_at,
|
|
386
416
|
started_at,
|
|
@@ -419,13 +449,6 @@ BEGIN
|
|
|
419
449
|
END;
|
|
420
450
|
$$ LANGUAGE plpgsql;
|
|
421
451
|
|
|
422
|
-
CREATE OR REPLACE FUNCTION delete_job(input_rid UUID)
|
|
423
|
-
RETURNS VOID AS $$
|
|
424
|
-
BEGIN
|
|
425
|
-
DELETE FROM job WHERE rid = input_rid;
|
|
426
|
-
END;
|
|
427
|
-
$$ LANGUAGE plpgsql;
|
|
428
|
-
|
|
429
452
|
CREATE OR REPLACE FUNCTION select_job(input_encryption_key TEXT, input_rid UUID)
|
|
430
453
|
RETURNS TABLE (
|
|
431
454
|
output_id BIGINT,
|
|
@@ -435,6 +458,7 @@ RETURNS TABLE (
|
|
|
435
458
|
output_options JSONB,
|
|
436
459
|
output_task_name VARCHAR(100),
|
|
437
460
|
output_parameters JSONB,
|
|
461
|
+
output_parameters_keyed JSONB,
|
|
438
462
|
output_status VARCHAR(50),
|
|
439
463
|
output_scheduled_at TIMESTAMP,
|
|
440
464
|
output_started_at TIMESTAMP,
|
|
@@ -454,7 +478,14 @@ BEGIN
|
|
|
454
478
|
job.worker_rid,
|
|
455
479
|
job.options,
|
|
456
480
|
job.task_name,
|
|
457
|
-
|
|
481
|
+
CASE
|
|
482
|
+
WHEN octet_length(job.parameters_encrypted) > 0 THEN pgp_sym_decrypt(job.parameters_encrypted, input_encryption_key::text)::jsonb
|
|
483
|
+
ELSE job.parameters
|
|
484
|
+
END AS parameters,
|
|
485
|
+
CASE
|
|
486
|
+
WHEN octet_length(job.parameters_keyed_encrypted) > 0 THEN pgp_sym_decrypt(job.parameters_keyed_encrypted, input_encryption_key::text)::jsonb
|
|
487
|
+
ELSE job.parameters_keyed
|
|
488
|
+
END AS parameters_keyed,
|
|
458
489
|
job.status,
|
|
459
490
|
job.scheduled_at,
|
|
460
491
|
job.started_at,
|
|
@@ -481,6 +512,7 @@ RETURNS TABLE (
|
|
|
481
512
|
output_options JSONB,
|
|
482
513
|
output_task_name VARCHAR(100),
|
|
483
514
|
output_parameters JSONB,
|
|
515
|
+
output_parameters_keyed JSONB,
|
|
484
516
|
output_status VARCHAR(50),
|
|
485
517
|
output_scheduled_at TIMESTAMP,
|
|
486
518
|
output_started_at TIMESTAMP,
|
|
@@ -500,7 +532,14 @@ BEGIN
|
|
|
500
532
|
job.worker_rid,
|
|
501
533
|
job.options,
|
|
502
534
|
job.task_name,
|
|
503
|
-
|
|
535
|
+
CASE
|
|
536
|
+
WHEN octet_length(job.parameters_encrypted) > 0 THEN pgp_sym_decrypt(job.parameters_encrypted, input_encryption_key::text)::jsonb
|
|
537
|
+
ELSE job.parameters
|
|
538
|
+
END AS parameters,
|
|
539
|
+
CASE
|
|
540
|
+
WHEN octet_length(job.parameters_keyed_encrypted) > 0 THEN pgp_sym_decrypt(job.parameters_keyed_encrypted, input_encryption_key::text)::jsonb
|
|
541
|
+
ELSE job.parameters_keyed
|
|
542
|
+
END AS parameters_keyed,
|
|
504
543
|
job.status,
|
|
505
544
|
job.scheduled_at,
|
|
506
545
|
job.started_at,
|
|
@@ -538,6 +577,7 @@ RETURNS TABLE (
|
|
|
538
577
|
output_options JSONB,
|
|
539
578
|
output_task_name VARCHAR(100),
|
|
540
579
|
output_parameters JSONB,
|
|
580
|
+
output_parameters_keyed JSONB,
|
|
541
581
|
output_status VARCHAR(50),
|
|
542
582
|
output_scheduled_at TIMESTAMP,
|
|
543
583
|
output_started_at TIMESTAMP,
|
|
@@ -557,7 +597,14 @@ BEGIN
|
|
|
557
597
|
job.worker_rid,
|
|
558
598
|
job.options,
|
|
559
599
|
job.task_name,
|
|
560
|
-
|
|
600
|
+
CASE
|
|
601
|
+
WHEN octet_length(job.parameters_encrypted) > 0 THEN pgp_sym_decrypt(job.parameters_encrypted, input_encryption_key::text)::jsonb
|
|
602
|
+
ELSE job.parameters
|
|
603
|
+
END AS parameters,
|
|
604
|
+
CASE
|
|
605
|
+
WHEN octet_length(job.parameters_keyed_encrypted) > 0 THEN pgp_sym_decrypt(job.parameters_keyed_encrypted, input_encryption_key::text)::jsonb
|
|
606
|
+
ELSE job.parameters_keyed
|
|
607
|
+
END AS parameters_keyed,
|
|
561
608
|
job.status,
|
|
562
609
|
job.scheduled_at,
|
|
563
610
|
job.started_at,
|
|
@@ -596,6 +643,7 @@ RETURNS TABLE (
|
|
|
596
643
|
output_options JSONB,
|
|
597
644
|
output_task_name VARCHAR(100),
|
|
598
645
|
output_parameters JSONB,
|
|
646
|
+
output_parameters_keyed JSONB,
|
|
599
647
|
output_status VARCHAR(50),
|
|
600
648
|
output_scheduled_at TIMESTAMP,
|
|
601
649
|
output_started_at TIMESTAMP,
|
|
@@ -615,7 +663,14 @@ BEGIN
|
|
|
615
663
|
job.worker_rid,
|
|
616
664
|
job.options,
|
|
617
665
|
job.task_name,
|
|
618
|
-
|
|
666
|
+
CASE
|
|
667
|
+
WHEN octet_length(job.parameters_encrypted) > 0 THEN pgp_sym_decrypt(job.parameters_encrypted, input_encryption_key::text)::jsonb
|
|
668
|
+
ELSE job.parameters
|
|
669
|
+
END AS parameters,
|
|
670
|
+
CASE
|
|
671
|
+
WHEN octet_length(job.parameters_keyed_encrypted) > 0 THEN pgp_sym_decrypt(job.parameters_keyed_encrypted, input_encryption_key::text)::jsonb
|
|
672
|
+
ELSE job.parameters_keyed
|
|
673
|
+
END AS parameters_keyed,
|
|
619
674
|
job.status,
|
|
620
675
|
job.scheduled_at,
|
|
621
676
|
job.started_at,
|
|
@@ -657,6 +712,13 @@ BEGIN
|
|
|
657
712
|
END;
|
|
658
713
|
$$ LANGUAGE plpgsql;
|
|
659
714
|
|
|
715
|
+
CREATE OR REPLACE FUNCTION delete_job(input_rid UUID)
|
|
716
|
+
RETURNS VOID AS $$
|
|
717
|
+
BEGIN
|
|
718
|
+
DELETE FROM job_archive WHERE rid = input_rid;
|
|
719
|
+
END;
|
|
720
|
+
$$ LANGUAGE plpgsql;
|
|
721
|
+
|
|
660
722
|
CREATE OR REPLACE FUNCTION select_job_from_archive(input_encryption_key TEXT, input_rid UUID)
|
|
661
723
|
RETURNS TABLE (
|
|
662
724
|
output_id BIGINT,
|
|
@@ -666,6 +728,7 @@ RETURNS TABLE (
|
|
|
666
728
|
output_options JSONB,
|
|
667
729
|
output_task_name VARCHAR(100),
|
|
668
730
|
output_parameters JSONB,
|
|
731
|
+
output_parameters_keyed JSONB,
|
|
669
732
|
output_status VARCHAR(50),
|
|
670
733
|
output_scheduled_at TIMESTAMP,
|
|
671
734
|
output_started_at TIMESTAMP,
|
|
@@ -685,7 +748,14 @@ BEGIN
|
|
|
685
748
|
job_archive.worker_rid,
|
|
686
749
|
job_archive.options,
|
|
687
750
|
job_archive.task_name,
|
|
688
|
-
|
|
751
|
+
CASE
|
|
752
|
+
WHEN octet_length(job_archive.parameters_encrypted) > 0 THEN pgp_sym_decrypt(job_archive.parameters_encrypted, input_encryption_key::text)::jsonb
|
|
753
|
+
ELSE job_archive.parameters
|
|
754
|
+
END AS parameters,
|
|
755
|
+
CASE
|
|
756
|
+
WHEN octet_length(job_archive.parameters_keyed_encrypted) > 0 THEN pgp_sym_decrypt(job_archive.parameters_keyed_encrypted, input_encryption_key::text)::jsonb
|
|
757
|
+
ELSE job_archive.parameters_keyed
|
|
758
|
+
END AS parameters_keyed,
|
|
689
759
|
job_archive.status,
|
|
690
760
|
job_archive.scheduled_at,
|
|
691
761
|
job_archive.started_at,
|
|
@@ -712,6 +782,7 @@ RETURNS TABLE (
|
|
|
712
782
|
output_options JSONB,
|
|
713
783
|
output_task_name VARCHAR(100),
|
|
714
784
|
output_parameters JSONB,
|
|
785
|
+
output_parameters_keyed JSONB,
|
|
715
786
|
output_status VARCHAR(50),
|
|
716
787
|
output_scheduled_at TIMESTAMP,
|
|
717
788
|
output_started_at TIMESTAMP,
|
|
@@ -731,7 +802,14 @@ BEGIN
|
|
|
731
802
|
job_archive.worker_rid,
|
|
732
803
|
job_archive.options,
|
|
733
804
|
job_archive.task_name,
|
|
734
|
-
|
|
805
|
+
CASE
|
|
806
|
+
WHEN octet_length(job_archive.parameters_encrypted) > 0 THEN pgp_sym_decrypt(job_archive.parameters_encrypted, input_encryption_key::text)::jsonb
|
|
807
|
+
ELSE job_archive.parameters
|
|
808
|
+
END AS parameters,
|
|
809
|
+
CASE
|
|
810
|
+
WHEN octet_length(job_archive.parameters_keyed_encrypted) > 0 THEN pgp_sym_decrypt(job_archive.parameters_keyed_encrypted, input_encryption_key::text)::jsonb
|
|
811
|
+
ELSE job_archive.parameters_keyed
|
|
812
|
+
END AS parameters_keyed,
|
|
735
813
|
job_archive.status,
|
|
736
814
|
job_archive.scheduled_at,
|
|
737
815
|
job_archive.started_at,
|
|
@@ -769,6 +847,7 @@ RETURNS TABLE (
|
|
|
769
847
|
output_options JSONB,
|
|
770
848
|
output_task_name VARCHAR(100),
|
|
771
849
|
output_parameters JSONB,
|
|
850
|
+
output_parameters_keyed JSONB,
|
|
772
851
|
output_status VARCHAR(50),
|
|
773
852
|
output_scheduled_at TIMESTAMP,
|
|
774
853
|
output_started_at TIMESTAMP,
|
|
@@ -788,7 +867,14 @@ BEGIN
|
|
|
788
867
|
job_archive.worker_rid,
|
|
789
868
|
job_archive.options,
|
|
790
869
|
job_archive.task_name,
|
|
791
|
-
|
|
870
|
+
CASE
|
|
871
|
+
WHEN octet_length(job_archive.parameters_encrypted) > 0 THEN pgp_sym_decrypt(job_archive.parameters_encrypted, input_encryption_key::text)::jsonb
|
|
872
|
+
ELSE job_archive.parameters
|
|
873
|
+
END AS parameters,
|
|
874
|
+
CASE
|
|
875
|
+
WHEN octet_length(job_archive.parameters_keyed_encrypted) > 0 THEN pgp_sym_decrypt(job_archive.parameters_keyed_encrypted, input_encryption_key::text)::jsonb
|
|
876
|
+
ELSE job_archive.parameters_keyed
|
|
877
|
+
END AS parameters_keyed,
|
|
792
878
|
job_archive.status,
|
|
793
879
|
job_archive.scheduled_at,
|
|
794
880
|
job_archive.started_at,
|
|
@@ -138,6 +138,23 @@ BEGIN
|
|
|
138
138
|
END;
|
|
139
139
|
$$ LANGUAGE plpgsql;
|
|
140
140
|
|
|
141
|
+
CREATE OR REPLACE FUNCTION delete_stale_workers(
|
|
142
|
+
input_cutoff_time TIMESTAMP
|
|
143
|
+
)
|
|
144
|
+
RETURNS INT
|
|
145
|
+
AS $$
|
|
146
|
+
DECLARE
|
|
147
|
+
affected_rows INT;
|
|
148
|
+
BEGIN
|
|
149
|
+
DELETE FROM worker
|
|
150
|
+
WHERE updated_at < input_cutoff_time
|
|
151
|
+
AND status = 'STOPPED';
|
|
152
|
+
|
|
153
|
+
GET DIAGNOSTICS affected_rows = ROW_COUNT;
|
|
154
|
+
RETURN affected_rows;
|
|
155
|
+
END;
|
|
156
|
+
$$ LANGUAGE plpgsql;
|
|
157
|
+
|
|
141
158
|
CREATE OR REPLACE FUNCTION select_worker(input_rid UUID)
|
|
142
159
|
RETURNS TABLE (
|
|
143
160
|
output_id BIGINT,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|