Coverage for gws-app/gws/base/job/__init__.py: 100%
1 statements
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-23 20:06 +0200
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-23 20:06 +0200
1"""Background jobs.
3Runs long tasks, such as printing or exporting, outside of the web request
4that started them. The client starts a job, receives its uid and polls its
5status until the job is complete, then fetches the result.
7Submodules
8----------
10- ``manager`` - the job manager (``root.app.jobMgr``). It stores jobs in a
11 SQLite database, schedules and runs them and handles status and cancel
12 requests.
13- ``worker`` - the base class for job workers, with access to the job record
14 for progress updates and cancellation checks.
16Jobs
17----
19A job record (``gws.Job``) holds the user, the worker class, the state,
20progress counters, a payload for the worker and the result. Records live in
21``jobs.<version>.sqlite`` in the misc directory, so that all server processes
22see the same jobs.
24A job goes through the states ``open`` (created), ``running`` and then
25``complete``, ``error`` or ``cancel``. ``schedule_job`` passes the job to the
26uWSGI spooler if it is available, otherwise the job runs at once in the
27current process. ``run_job`` marks the job as running atomically, so a job runs
28only once, imports the worker class and calls its ``run`` class method. An
29exception in the worker, other than ``gws.JobTerminated``, puts the job into
30the ``error`` state.
32Workers
33-------
35A worker is a class with a ``run(root, job)`` class method, usually a subclass
36of ``worker.Object``. While working, it reports progress with ``update_job``
37and finally stores the result. ``get_job`` and ``update_job`` raise
38``gws.JobTerminated`` when the job is no longer running, for example because
39it was cancelled, which ends the worker.
41Jobs belong to the user who created them; status, cancel and result requests
42from other users are answered with ``gws.NotFoundError``.
44Example::
46 class MyWorker(gws.base.job.worker.Object):
47 @classmethod
48 def run(cls, root, job):
49 w = cls(root, job.user, job)
50 w.work(job.payload)
52 def work(self, payload):
53 self.update_job(numSteps=len(payload['items']))
54 for n, item in enumerate(payload['items'], 1):
55 ...
56 self.update_job(step=n)
57 self.update_job(state=gws.JobState.complete, result={'count': n})
59 mgr = root.app.jobMgr
60 job = mgr.create_job(MyWorker, user, payload={'items': [...]})
61 job = mgr.schedule_job(job)
62 return mgr.job_status_response(job)
63"""
65from . import manager, worker