Hooking into a service’s lifecycle

While handle is the main method each service needs to implement, hooks are methods of a service that can be optionally overridden in order to execute additional code before or after several defined points in a service’s lifecycle.

Which methods can be implemented depends on how a service is invoked - some methods are common to all access mechanisms while the rest of them is specific only to jobs executed through the scheduler.

Any exceptions raised in before_add_to_store will mean a service won’t be deployed. For all other hooks, if an exception is raised, it will be caught by Zato, logged, and the next method will be called as though there was no exception in the previous one.

You can use the environ dictionary to pass data down from a hook to another.

Common methods

These methods can be overridden regardless of the means a service will be executed with, no matter its channel, if any, or if it’s invoked through the scheduler or not.

Method Notes
before_add_to_store Static method that will be executed by each worker when a server starts up. A service will be deployed by that worker only if the method returns True and this is the value before_add_to_store returns by default.
after_add_to_store Static method that will be executed by each worker right after a service has been successfully deployed.
accept If False, the service won’t be executed at all. Defaults to True.
before_handle Executed right before a service’s handle will be called
after_handle Executed right after a service’s handle has been called
finalize_handle Executed after Zato has finished additional bookkeeping such as storing service statistics in Redis so that further attributes are available in finalize_handle - they can’t be accessed in handle or after_handle
../../_images/service-hooks-common.png
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from zato.server.service import Service

class MyService(Service):

    @staticmethod
    def before_add_to_store(logger):
        logger.info('Adding to store {}'.format(MyService.get_name()))

        # Don't forget to return True, otherwise the service won't be deployed
        return True

    @staticmethod
    def after_add_to_store(logger):
        logger.info('Added to store {}'.format(MyService.get_name()))

    def before_handle(self):
        self.logger.info('before_handle called')

    def handle(self):
        self.logger.info('handle called')

    def after_handle(self):
        self.logger.info('after_handle called')

    def finalize_handle(self):
        self.logger.info('finalize_handle called')
        self.logger.info('processing_time {} ms'.format(self.processing_time))
        self.logger.info('processing_time_raw {}'.format(self.processing_time_raw))
INFO - Adding to store service-hooks.my-service
INFO - Added to store service-hooks.my-service
...
...
INFO - before_handle called
INFO - handle called
INFO - after_handle called
INFO - finalize_handle called
INFO - processing_time 0 ms
INFO - processing_time_raw 0:00:00.000537

Common and additional scheduler-specific methods

A scheduler-initiated service can access all the common methods and a set of supplementary ones, and even then, some will depend on the job's type.

Method Notes
before_add_to_store Documented along with other common methods
after_add_to_store Documented along with other common methods
accept Documented along with other common methods
before_job Executed before a service's handle will be called but only if the service has been triggered by the scheduler, regardless of the job type
before_one_time_job Executed before a service's handle will be called but only if the service has been triggered by the scheduler and its job_type is 'one_time'
before_interval_based_job 〃 when job_type is 'interval_based'
before_cron_style_job 〃 when job_type is 'cron_style'
before_handle Documented along with other common methods
after_handle Documented along with other common methods
after_job Executed after a service's handle has been called but only if the service has been triggered by the scheduler, regardless of the job type
after_one_time_job Executed after a service's handle has been called but only if the service has been triggered by the scheduler and its job_type is 'one_time'
after_interval_based_job 〃 when job_type is 'interval_based'
after_cron_style_job 〃 when job_type is 'cron_style'
finalize_handle Documented along with other common methods
../../_images/service-hooks-common-scheduler.png
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
from zato.server.service import Service

class MyService(Service):

    @staticmethod
    def before_add_to_store(logger):
        logger.info('before_add_to_store called')

        # Don't forget to return True, otherwise the service won't be deployed
        return True

    @staticmethod
    def after_add_to_store(logger):
        logger.info('after_add_to_store called')

    def before_job(self):
        self.logger.info('before_job called')

    def before_one_time_job(self):
        raise NotImplementedError()

    def before_interval_based_job(self):
        self.logger.info('before_interval_based_job called')

    def before_cron_style_job(self):
        raise NotImplementedError()

    def before_handle(self):
        self.logger.info('before_handle called')

    def handle(self):
        self.logger.info('handle called')

    def after_handle(self):
        self.logger.info('after_handle called')

    def after_job(self):
        self.logger.info('after_job called')

    def after_one_time_job(self):
        raise NotImplementedError()

    def after_interval_based_job(self):
        self.logger.info('after_interval_based_job called')

    def after_cron_style_job(self):
        raise NotImplementedError()

    def finalize_handle(self):
        self.logger.info('finalize_handle called')
        self.logger.info('processing_time {} ms'.format(self.processing_time))
        self.logger.info('processing_time_raw {}'.format(self.processing_time_raw))
INFO - Adding to store service-hooks.my-service
INFO - Added to store service-hooks.my-service
...
...
INFO - before_job called
INFO - before_interval_based_job called
INFO - before_handle called
INFO - handle called
INFO - after_handle called
INFO - after_job called
INFO - after_interval_based_job called
INFO - finalize_handle called
INFO - processing_time 1 ms
INFO - processing_time_raw 0:00:00.001397