Run services on a schedule

Run services on an interval or at a specific time.

The scheduler invokes your services on an interval or at a specific time. Jobs are created in the Dashboard or from Python and no service code changes are needed for a service to become a scheduled one.

For a step-by-step introduction, see the Python scheduler tutorial.

Invoke services on an interval

To create a job, go to Scheduler > Config in the Dashboard, click Create a new job and fill in the form:

  1. Name: Nightly Sync
  2. Service: the service the scheduler invokes on each run
  3. Every: how often to run it, e.g. every 30 minutes
  4. Click OK
New interval-based job

The service is invoked each time the job fires, and any extra data provided in the job's definition is available to the service as text in self.request.input:

# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class MyService(Service):

    def handle(self):
        self.logger.info('Message received: %s', self.request.input)

Schedule one-time jobs in Python

To run a service once, at a specific time, call self.schedule.onetime. The example below schedules another service for a specific moment - the prefix parameter makes the job easy to find in the Dashboard and logs:

# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class MyTarget(Service):

    def handle(self):
        self.logger.warn('I was invoked with %s', self.request.input)

class Scheduler(Service):

    def handle(self):

        # This can be used to make it easier to understand which scheduled job is which
        prefix = 'user@example.com'

        # This is what the target service is going to receive on input
        data = {
            'my.key': 'my.value'
        }

        # This is when the job should start, note that the time must be in UTC
        start_date = '2027-07-29 11:35:49'

        # This is the call that schedules the job
        self.schedule.onetime(self, MyTarget, prefix=prefix, start_date=start_date, data=data)

Schedule interval-based jobs in Python

To create interval-based jobs from code, invoke the built-in zato.scheduler.job.create service:

# stdlib
from datetime import datetime

# Zato
from zato.server.service import Service

class MyService(Service):

    def handle(self):

        #
        # We schedule a job here that will run once per hour
        #

        request = {
            'name': 'my-job-1',
            'is_active': True,
            'service': 'zato.ping',
            'job_type': 'interval_based',
            'start_date': datetime.utcnow().isoformat(), # Always in UTC
            'hours': 1
        }

        self.invoke('zato.scheduler.job.create', request)
Note: An interval-based job counts its runs from its start date - the first run is at the start date, the next one an interval later, and so on. With a start date in the past, the runs are still counted from it, and the first one to happen is the next one that has not passed yet. When a server restarts, each job resumes with the first run that falls after the server is back. Runs that fell into the time the server was down are not repeated - if the server was down from 02:00 to 05:00, the 03:00 run does not happen, the next run is at 03:00 the following day, and the time of the run stays at 03:00 rather than moving to 05:00. There is never a burst of catch-up runs after a restart.
Note: Runs repeat at fixed intervals in UTC. A daily job therefore runs at the same UTC time all year, and its local time moves by an hour when daylight saving time begins or ends. No run is skipped or repeated at these changes.

See also

FeatureWhat it does
IMAPPoll mailboxes on a schedule with an auto-created job
Config filesKeep a job's settings outside code
SMTPSend email from scheduled services

Learn more