Watch Functions

The ResConfig object is aware of changes to its configuration. Watch functions can be registered to watch changes happening at any nested key to act on them.

The following example shows how a watch function, named manage_db_host(), can be triggered on changes happening for the db.host item in configuration:

import signal
from resconfig import Action, ResConfig

config = ResConfig(load_on_init=False)

@config.watch("db.host")
def manage_db_host(action, old, new):
    if action == Action.ADDED:
        # Initialize database connection?
    elif action == Action.MODIFIED:
        # Change database connection?
    elif action == Action.RELOADED:
        # Refresh database connection?
    elif action == Action.REMOVED:
        # Clean up on database connection?

def reload(signum=None, stack_frame=None):
    config.reload()

signal.signal(signal.SIGHUP, reload)  # run reload on SIGHUP

config.load()

Here, the manage_db_host() function is called whenever a change occurs at the db.host item in the configuration and can decide what to do with the old and/or new values based on the actual Action. In this example, the configuration reload function is a handler for SIGHUP and is triggered when the process receives the signal, for example, via kill -SIGHUP <pid> where <pid> is the application process ID.

The watch function can be registered in a few different ways: watch(), register(), and the watchers argument to the ResConfig initializer. There are no differences among the styles in terms of functionality. The decorator style:

@config.watch("db.host")
def watch_function(action, old, new):
    ...

The method style:

def watch_function(action, old, new):
    ...

config.register("db.host", watch_function)

The initial argument style:

def watch_function(action, old, new):
    ...

config = ResConfig(watchers={"db.host": watch_function})