linod
: asynchronous Lino daemon¶
The lino.modlib.linod
plugin adds functionality for background work such
as running system tasks, sending notifications, and logging to the
lino.log
from multiple processes. It uses the ASGI interface to run an
asynchronous Lino daemon process.
What it does¶
The Lino daemon process is responsible for running the scheduled background jobs defined by your application. This includes for example:
Send out emails for notifications
Run daily maintenance tasks such as
checkdata
orchecksummaries
.
Usage¶
Applications can register a job using the dd.api.schedule_often()
or
dd.api.schedule_daily()
decorators. For example (taken from
lino.modlib.checkdata
):
@dd.schedule_daily()
def checkdata(ar):
"""Run all data checkers."""
check_data(fix=False)
The code for the example above should be in one of your application's
models.py
modules.
You can see a status of these jobs by running:
$ cd ~/projects/mysite
$ python manage.py linod
How to activate¶
A site maintainer can activate this plugin automatically by setting the
use_lino
site setting to True.
- use_linod¶
Whether to install the
lino.modlib.linod
plugin and activate asynchronous functionality.
>>> import lino
>>> lino.startup('lino_book.projects.noi1e.settings.demo')
>>> from lino.api.doctest import *
System tasks¶
- class lino.modlib.linod.Procedure¶
Is basically a
Job
which contains a functionfunc
to run at default interval given byevery_unit
andevery_value
.The default interval can be overridden by
JobRule
.- func¶
The function to run as a system task.
- Type:
Callable[[
BaseRequest
], None]
- start_datetime¶
The time at which this task should run first.
- Type:
datetime.datetime
- run(self, ar)¶
Calls the function stored in
func
passing ar as a positional argument.- Parameters:
ar -- an instance of
BaseRequest
- class lino.modlib.linod.Procedures¶
The choicelist that contains instances
Procedure
as choices.>>> rt.show(linod.Procedures) ============================== ============================== ============================== value name text ------------------------------ ------------------------------ ------------------------------ clear_too_old_job_history clear_too_old_job_history clear_too_old_job_history event_notification_scheduler event_notification_scheduler event_notification_scheduler checksummaries checksummaries checksummaries checkdata checkdata checkdata send_pending_emails_often send_pending_emails_often send_pending_emails_often send_pending_emails_daily send_pending_emails_daily send_pending_emails_daily clear_seen_messages clear_seen_messages clear_seen_messages ============================== ============================== ==============================
- class lino.modlib.linod.LogLevels¶
A choicelist with the equivalent log levels from the logging module.
- class lino.modlib.linod.JobRule¶
Overrides the recurrent rule of a
Procedure
.A subclass of
Sequenced
andRecurrenceSet
.- name¶
Some name for this job rule.
- Type:
str
- cancelled¶
Tells whether the task should be ignored.
cancelled
is set to True if the tasks fails and raises an exception, otherwise can be set cancelled from the ui.- Type:
bool
- log_level¶
Tells what sort of messeages to put into the
Job.message
field.- Type:
- Value:
- run(self, ar, lgr=None) Job ¶
Performs a routine job.
Calls
self.procedure.run
.Cancels the rule in case of a failure.
Creates an instance of
Job
- Parameters:
ar -- An instance of
BaseRequest
lgr -- Logger obtained by calling logging.getLogger.
- Returns:
An instance of
Job
.
- class lino.modlib.linod.Job¶
A historical record of a system task.
- start_datetime¶
Tells at what time exactly this job started.
- Type:
datetime.datetime
- message¶
Stores information about the job, mostly logs.
- class lino.modlib.linod.JobsByRule¶
- class lino.modlib.linod.tasks.Tasks¶
The base class that manages the system tasks.
- setup(self)¶
Gathers all the jobs defined using
dd.api.schedule_often()
anddd.api.schedule_daily()
decorator.This method is called at startup of the linod worker process. Also does cleaning up of removed tasks and reactivating the
cancelled
tasks.>>> from lino.modlib.linod.tasks import Tasks >>> tasks = Tasks() >>> tasks.setup()
- run(self) datetime.datetime ¶
Runs the system tasks which are due for the current time.
- Returns:
an instance of datetime.datetime; tells the parent scope at what time the next call to
run()
method should be done.
- status(self) list[str] ¶
Returns the status of all the tasks.
>>> for task_status in tasks.status(): ... print(task_status) ... Job rule #1 <Procedures.clear_too_old_job_history every 1 daily> next run at: ... Job rule #2 <Procedures.event_notification_scheduler every 300 secondly> next run at: ... Job rule #3 <Procedures.checksummaries every 1 daily> next run at: ... Job rule #4 <Procedures.checkdata every 1 daily> next run at: ... Job rule #5 <Procedures.send_pending_emails_often every 10 secondly> next run at: ... Job rule #6 <Procedures.send_pending_emails_daily every 1 daily> next run at: ... Job rule #7 <Procedures.clear_seen_messages every 1 daily> next run at: ...
- create_rule()¶
Creates a
JobRule
for a givenProcedure
- Parameters:
procedure -- an instance of
Procedure
- cancel_rule()¶
Sets
Job.cancelled
to True for a given rule.- Parameters:
rule -- an instance of
JobRule
- class lino.modlib.linod.SetupTasks¶
An action to adjust the database objects to the latest changes.
Should be run only in development environment where no linod worker present. A production run of linod worker does this on each spin up by calling
Tasks.setup
.
- class lino.modlib.linod.RunJob¶
An action to run a job immediately.
Simulating the daemon in a developer environment¶
To run the Lino daemon in a development environment run python manage.py
runworker `linod_{{project_name}}
here if your project name is my_project you
will need to run python manage.py runworker linod_my_project
. And
afterwards to initiate the background tasks and logging you will have to run the
python manage.py initiate_linod
command in an another terminal.
Usage for developers¶
The lino.modlib.linod
plugin is dependent on a running redis-server in
the background and also requires the django-channels, channels-redis
Python packages to be installed.
To install redis on a Debian-based Linux distribution run the following command as root:
$ apt update
$ apt install redis
To install the dependent python packages run the following command after activating your Python environment:
$ pip install django-channels channels-redis
Now you simply go to your project directory and invoke the admin command:
$ cd ~/projects/mysite
$ python manage.py runworker linod_mysite
This process will run as long as you don't kill it, e.g. until you hit Ctrl-C.
Open up another terminal window, on which invoke the following command to initiate the background task's cor-routine and logger cor-routine:
$ cd ~/projects/mysite
$ python manage.py initiate_linod