Timer Stores | Rasa Documentation

Timer Stores in Rasa

Rasa maintains one active timer per conversation to track inactivity. To ensure timers persist across server restarts and work in multi-pod deployments, Rasa uses a timer store. Rasa provides built-in timer store implementations to suit different deployment scenarios and requirements.

InMemoryTimerStore (default)

RedisTimerStore

Description

RedisTimerStore maintains conversation timers using Redis as a persistence layer. This is the recommended option for production deployments as it supports persistence across server restarts and works in multi-pod environments.

With Redis:

Configuration

To set up the timer store with Redis the following steps are required:

  1. Add required configuration to your endpoints.yml
timer_store:
       type: "redis"
       host: <host of the redis instance, e.g. localhost>
       port: <port of your redis instance, usually 6379>
       username: <username used for authentication>
       password: <password used for authentication>
       db: <number of your database within redis, e.g. 0. Not used in cluster mode>
       key_prefix: <alphanumeric value to prepend to timer store keys>
       socket_timeout: <time in seconds after which redis commands time out, default 10>
       poll_interval: <interval in seconds between polling for expired timers, default 1.0>
       # transit encryption parameters
       use_ssl: <whether or not the communication is encrypted, default false>
       ssl_keyfile: <path to an ssl private key, only used if use_ssl is true>
       ssl_certfile: <path to an ssl certificate, only used if use_ssl is true>
       ssl_ca_certs: <path to a file of concatenated CA certificates in PEM format, only used if use_ssl is true>
       # high availability parameters
       deployment_mode: <standard, cluster, or sentinel>
       endpoints: <list of redis cluster/sentinel node addresses in the format host:port>
       sentinel_service: <name of the redis sentinel service, only used in sentinel mode>

Fallback Timer Store

If Redis is configured but becomes unavailable, Rasa automatically falls back to the InMemoryTimerStore. Sessions continue to be managed without crashing, and a warning is logged when the fallback is activated. When Redis recovers, Rasa resumes using it and logs that the fallback has been deactivated.

Custom Timer Stores

If you need a timer store which is not available out of the box, you can implement your own. To write a custom timer store, extend SessionTimerStore from rasa.core.timer_stores.timer_store. Your constructor must accept an endpoint_config parameter:

from rasa.core.timer_stores.timer_store import SessionTimerStore
from rasa.utils.endpoints import EndpointConfig

class MyCustomTimerStore(SessionTimerStore):
  def __init__(self, endpoint_config: EndpointConfig = None):
      ...

Your custom timer store class must implement all of the following methods:

  def close(self) -> None:
    """Close and clean up the timer store."""
  async def store_timer(
    self,
    sender_id: str,
    session_id: Optional[str],
    scheduled_time: float,
    metadata: Optional[Dict[str, Any]] = None,
  ) -> None:
    """Store a session timer for the given conversation.

Args:
        sender_id: The conversation ID.
        session_id: The current session ID, used to validate the timer
            has not been superseded when it fires.
        scheduled_time: Unix timestamp (seconds) when the timer should fire.
        metadata: Optional key-value data to attach to the timer.
    """
  async def delete_timer(
    self,
    sender_id: str,
    only_if_scheduled_time: Optional[float] = None,
  ) -> bool:
    """Delete the timer for the given conversation.

Args:
        sender_id: The conversation ID.
        only_if_scheduled_time: If set, delete only when the stored timer's
            scheduled_time equals this value (for atomic multi-pod claiming).
            If None, delete unconditionally.

Returns:
        True if a timer was found and deleted, False otherwise.
    """
  async def get_timer(self, sender_id: str) -> Optional[SessionTimer]:
    """Get the timer for the given conversation.

Args:
        sender_id: The conversation ID.

Returns:
        The SessionTimer if one exists for this conversation, None otherwise.
    """
  async def get_expired_timers(
    self, cutoff_time: Optional[float] = None
  ) -> List[SessionTimer]:
    """Return all timers that have expired.

Args:
        cutoff_time: Unix timestamp threshold. Timers with
            scheduled_time <= cutoff_time are returned.
            Defaults to the current time if None.

Returns:
        List of expired SessionTimer objects. Must not delete them.
    """

The base class provides two helpers that can be used by the get_expired_timers method:

Another built-in helper method available for use in your custom timer store is:

Configuration

Put the module path to your custom timer store class in endpoints.yml under the timer_store key. Any additional fields are passed through as part of the EndpointConfig and are accessible via endpoint_config.kwargs:

timer_store:
  type: path.to.your.module.MyCustomTimerStore
  a_parameter: a value
  another_parameter: another value