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

1"""Background jobs. 

2 

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. 

6 

7Submodules 

8---------- 

9 

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. 

15 

16Jobs 

17---- 

18 

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. 

23 

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. 

31 

32Workers 

33------- 

34 

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. 

40 

41Jobs belong to the user who created them; status, cancel and result requests 

42from other users are answered with ``gws.NotFoundError``. 

43 

44Example:: 

45 

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) 

51 

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}) 

58 

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""" 

64 

65from . import manager, worker