plain.jobs 0.36.2__py3-none-any.whl → 0.37.0__py3-none-any.whl

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.

Potentially problematic release.


This version of plain.jobs might be problematic. Click here for more details.

plain/jobs/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # plain-jobs changelog
2
2
 
3
+ ## [0.37.0](https://github.com/dropseed/plain/releases/plain-jobs@0.37.0) (2025-10-22)
4
+
5
+ ### What's changed
6
+
7
+ - Added `JobMiddleware` abstract base class for creating custom job middleware ([29e5c6df1a](https://github.com/dropseed/plain/commit/29e5c6df1a))
8
+ - Changed "preparing to execute job" log message from `logger.info` to `logger.debug` to reduce log noise ([8e25856639](https://github.com/dropseed/plain/commit/8e25856639))
9
+
10
+ ### Upgrade instructions
11
+
12
+ - If you have custom job middleware, update them to inherit from `JobMiddleware` and implement the `process_job()` method instead of `__call__()`
13
+
14
+ ## [0.36.3](https://github.com/dropseed/plain/releases/plain-jobs@0.36.3) (2025-10-20)
15
+
16
+ ### What's changed
17
+
18
+ - Added garbage collection back to worker processes after job completion to help manage memory usage ([aafe3ace02](https://github.com/dropseed/plain/commit/aafe3ace02))
19
+
20
+ ### Upgrade instructions
21
+
22
+ - No changes required
23
+
3
24
  ## [0.36.2](https://github.com/dropseed/plain/releases/plain-jobs@0.36.2) (2025-10-20)
4
25
 
5
26
  ### What's changed
plain/jobs/__init__.py CHANGED
@@ -1,4 +1,5 @@
1
1
  from .jobs import Job
2
+ from .middleware import JobMiddleware
2
3
  from .registry import register_job
3
4
 
4
- __all__ = ["Job", "register_job"]
5
+ __all__ = ["Job", "JobMiddleware", "register_job"]
plain/jobs/middleware.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from abc import ABC, abstractmethod
3
4
  from collections.abc import Callable
4
5
  from typing import TYPE_CHECKING
5
6
 
@@ -9,11 +10,32 @@ if TYPE_CHECKING:
9
10
  from .models import JobProcess, JobResult
10
11
 
11
12
 
12
- class AppLoggerMiddleware:
13
- def __init__(self, run_job: Callable[[JobProcess], JobResult]) -> None:
13
+ class JobMiddleware(ABC):
14
+ """
15
+ Abstract base class for job middleware.
16
+
17
+ Subclasses must implement process_job() to handle the job execution cycle.
18
+
19
+ Example:
20
+ class MyJobMiddleware(JobMiddleware):
21
+ def process_job(self, job: JobProcess) -> JobResult:
22
+ # Pre-processing
23
+ result = self.run_job(job)
24
+ # Post-processing
25
+ return result
26
+ """
27
+
28
+ def __init__(self, run_job: Callable[[JobProcess], JobResult]):
14
29
  self.run_job = run_job
15
30
 
16
- def __call__(self, job: JobProcess) -> JobResult:
31
+ @abstractmethod
32
+ def process_job(self, job: JobProcess) -> JobResult:
33
+ """Process the job and return a result. Must be implemented by subclasses."""
34
+ ...
35
+
36
+
37
+ class AppLoggerMiddleware(JobMiddleware):
38
+ def process_job(self, job: JobProcess) -> JobResult:
17
39
  with app_logger.include_context(
18
40
  job_request_uuid=str(job.job_request_uuid), job_process_uuid=str(job.uuid)
19
41
  ):
plain/jobs/workers.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import gc
3
4
  import logging
4
5
  import multiprocessing
5
6
  import os
@@ -143,7 +144,7 @@ class Worker:
143
144
  time.sleep(1)
144
145
  continue
145
146
 
146
- logger.info(
147
+ logger.debug(
147
148
  'Preparing to execute job job_class=%s job_request_uuid=%s job_priority=%s job_source="%s" job_queues="%s"',
148
149
  job_request.job_class,
149
150
  job_request.uuid,
@@ -326,7 +327,7 @@ def process_job(job_process_uuid: str) -> None:
326
327
  for middleware_path in reversed(settings.JOBS_MIDDLEWARE):
327
328
  middleware_class = import_string(middleware_path)
328
329
  middleware_instance = middleware_class(middleware_chain)
329
- middleware_chain = middleware_instance
330
+ middleware_chain = middleware_instance.process_job
330
331
 
331
332
  job_result = middleware_chain(job_process)
332
333
 
@@ -353,3 +354,4 @@ def process_job(job_process_uuid: str) -> None:
353
354
  logger.exception(e)
354
355
  finally:
355
356
  request_finished.send(sender=None)
357
+ gc.collect()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plain.jobs
3
- Version: 0.36.2
3
+ Version: 0.37.0
4
4
  Summary: Process background jobs with a database-driven job queue.
5
5
  Author-email: Dave Gaeddert <dave.gaeddert@dropseed.dev>
6
6
  License-File: LICENSE
@@ -1,18 +1,18 @@
1
- plain/jobs/CHANGELOG.md,sha256=jCOSyuP7LrxP-tkEk4YgHbESlUNjsHhsnrL_Yk7fvqs,12604
1
+ plain/jobs/CHANGELOG.md,sha256=NWsCgXUWmrbBni77ILNwuF0HYJOkbf02JunTu09syF0,13534
2
2
  plain/jobs/README.md,sha256=Xuhz2Q48G9WeGCh5OWGVBlaSea4eKCqWzcTAtZRrS0I,6835
3
- plain/jobs/__init__.py,sha256=p2ATql3HyPzPTV34gJQ04caT7tcNQLbBGM6uIoDPbjo,92
3
+ plain/jobs/__init__.py,sha256=yN6m5CxQuzB5tKVXVPwGSSh2jtwQybVDHj1V4M3z2F0,147
4
4
  plain/jobs/admin.py,sha256=t1UEchq1-Eews_wPsVUofaqbzPaYpb-8H1bUlA59JGI,6785
5
5
  plain/jobs/chores.py,sha256=oyVU-BfcJxMM3eK2_umn38N2mBsNpcDrZfpeEQju_DA,528
6
6
  plain/jobs/cli.py,sha256=PPoT7xjl818BZnmI0yA_UCLEQkzl_Tv1_hiuJW9UE-Q,5911
7
7
  plain/jobs/config.py,sha256=PQsl-LxWsWLnjC98f0mvtdcCOuXvXKDMjrCRf1fq44Y,550
8
8
  plain/jobs/default_settings.py,sha256=r_95ucg_KY1XW1jarZy8VO3p-ylbllKMUrHzOPJiX6U,227
9
9
  plain/jobs/jobs.py,sha256=-tBt_5V2KwGui7OpBcq1gANVn3YvKEoBJn0MXNlnKlo,7761
10
- plain/jobs/middleware.py,sha256=bz8aPBY0RbtLS4kic8mzPOd3EyQFCVRQ2uTCttT3RpE,573
10
+ plain/jobs/middleware.py,sha256=iQbVPnQz91OpkfNFsDh6-G0RLWW7KxYssUKdk7JEdNE,1228
11
11
  plain/jobs/models.py,sha256=TYOjMT0dSF69uzfY2m13ZPwo6G0WOVJUbgJvsDFxBhI,15889
12
12
  plain/jobs/parameters.py,sha256=t9PwEZgwNCJx3YobsT-jfaVZdfMBS54XJcBrT9Wnsg0,6313
13
13
  plain/jobs/registry.py,sha256=Rwn5Htll10e549vD2Mu0oyoDynyHhE0bGYZ2bq9uzPU,1679
14
14
  plain/jobs/scheduling.py,sha256=fqpFnVoIIV-muf82WzuLyioSmiilfZ76KFjXzt8grIk,7851
15
- plain/jobs/workers.py,sha256=q8bixbv1m5iZMiQRYVfGGzlDF80T12zm0QNE1EUatj4,13514
15
+ plain/jobs/workers.py,sha256=eqaFqHRtpzh2QBdQ0dfUSMXMzpoxZOUlxw-7N661cUs,13558
16
16
  plain/jobs/migrations/0001_initial.py,sha256=EIgIEMVyTsStyx9dmKM8Jb_hwn694Yo31-74DZkNTqo,9452
17
17
  plain/jobs/migrations/0002_job_span_id_job_trace_id_jobrequest_span_id_and_more.py,sha256=ph5BwwOAwdfjdNh9RItYmX_IA29lO-Dd9GymYzvChXQ,1953
18
18
  plain/jobs/migrations/0003_rename_job_jobprocess_and_more.py,sha256=EdLucHxiH_QshLL2peIcMULRCQyFMPxh476AxCxW5Wk,2615
@@ -21,7 +21,7 @@ plain/jobs/migrations/0005_rename_constraints_and_indexes.py,sha256=PDGpOw6__tVf
21
21
  plain/jobs/migrations/0006_alter_jobprocess_table_alter_jobrequest_table_and_more.py,sha256=FY0_pcw0mL8MkUSatpDXWtA_xQw0kTZBGIyjLcmYeJE,546
22
22
  plain/jobs/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  plain/jobs/templates/admin/plainqueue/jobresult_detail.html,sha256=Ybp1s_dARo_bFDcLEzEfETheP8SzqHHE_NNSKhv_eh8,198
24
- plain_jobs-0.36.2.dist-info/METADATA,sha256=sGER074rn4FofXat4ApF4UQK3G2In_Tl7J3-_zf_Br8,7162
25
- plain_jobs-0.36.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
26
- plain_jobs-0.36.2.dist-info/licenses/LICENSE,sha256=cvKM3OlqHx3ijD6e34zsSUkPvzl-ya3Dd63A6EHL94U,1500
27
- plain_jobs-0.36.2.dist-info/RECORD,,
24
+ plain_jobs-0.37.0.dist-info/METADATA,sha256=geJ8q9B-FRjIjkx069lyjHp8vnaN2KrbZ3hpJ3Y9IEE,7162
25
+ plain_jobs-0.37.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
26
+ plain_jobs-0.37.0.dist-info/licenses/LICENSE,sha256=cvKM3OlqHx3ijD6e34zsSUkPvzl-ya3Dd63A6EHL94U,1500
27
+ plain_jobs-0.37.0.dist-info/RECORD,,