Skip to content

Index

Scheduled Scheduled

Scheduled jobs in Python's `pyproject.toml`.

Test Publish Coverage Python package version npm package version


Documentation: https://scheduled.work

Source Code: https://github.com/tiangolo/scheduled


Description

This is a specification for declaring recurring scheduled jobs in Python projects, in pyproject.toml.

It defines how jobs are declared and how providers would run them.

It does not provide a specific implementation for running scheduled jobs, because that is provider specific.

Example

Imagine a file app/jobs.py with:

def clean_files():
    print("Running cleanup...")

You could define a scheduled job to run that function once per day with:

[tool.scheduled.clean-files]
every = "day"
entrypoint = "app.jobs:clean_files"

Scheduled Format

Each job has a unique ID and two required fields: every and entrypoint.

[tool.scheduled.<job-id>]
every = "<cadence>" # minute, hour, day, week, month
entrypoint = "<module>:<function>"

Job ID

Scheduled jobs are configured as TOML tables under tool.scheduled.

tool.scheduled is the predefined namespace. <job-id> is the unique ID of the job.

every

How often to run the job.

For example every = "day" would run the job once per day.

[tool.scheduled.clean-files]
every = "day"
entrypoint = "app.jobs:clean_files"

Supported values are:

  • minute
  • hour
  • day
  • week
  • month

Providers should run each job once per configured cadence. For example, with every = "day", the provider should run the job once per day.

Accounting for failures and errors, providers should run the job at least once per cadence. If there's a failure and it's not known if the job was run or not, the provider should attempt to run the job again.

Users should write the code in a way that is idempotent and can be safely run multiple times if needed.

Providers might support only a subset of these cadence values. For example, a provider might only support every = "day" and every = "month", but not every = "minute" or every = "hour".

When the Job Runs

Providers may assign each job a fixed time within its cadence. For example, with every = "day", a provider might assign 10:30 to a specific job, then run that job every day at 10:30.

The same applies to the other cadence values. For example, with every = "hour", a provider might assign :15 and run the job every hour at :15.

Providers would then normally show this assigned time in their UI, so users can see when the job is scheduled to run.

Providers might do this by hashing the job ID (for example with SHA256) to map the job to a specific time within the cadence.

Being able to distribute during the cadence period like this allows providers to spread out the load of running many jobs.

Providers might provide a way to trigger a job manually outside of its normal cadence, which is in particular useful for testing.

entrypoint

Python callable to run, in the format:

importable.module:some_callable

For example, for a scheduled job like:

def clean_files():
    ...

in a file at app/jobs.py, the config could look like:

[tool.scheduled.clean-files]
every = "day"
entrypoint = "app.jobs:clean_files"

The entrypoint format, like:

importable.module:some_callable

...is equivalent to:

from importable.module import some_callable

some_callable()

So, app.jobs:clean_files is equivalent to:

from app.jobs import clean_files

clean_files()

License

This project is licensed under the terms of the MIT license.