collective.redismemoize.client#

The Redis connection and its circuit breaker.

The Redis connection: created lazily, per process, behind a circuit breaker.

The client is created on first use and recreated when the process id changes, so a server that forks workers after startup never shares a socket between processes.

The breaker is what keeps a Redis outage from becoming a Plone outage. After a failure, Connection.available() is False for retry_after seconds and every cached function goes straight to its RAM cache, without waiting for a timeout per call. The first call after that tries Redis again; a success closes the breaker, a failure keeps it open for another period. One WARNING is logged when the breaker opens and one INFO when it closes, never one line per request.

This module is pure Python and never imports Zope.

collective.redismemoize.client.ERRORS: tuple[type[BaseException], ...] = (<class 'redis.exceptions.RedisError'>, <class 'OSError'>)#

The exceptions that mean Redis, or the network to it, failed.

collective.redismemoize.client.ClientFactory#

Builds a client from the settings. Replaced by tests and by collective.redismemoize.testing to point at fakeredis.

alias of Callable[[Settings], Any]

collective.redismemoize.client.default_factory(settings)[source]#

Create a redis-py client for the configured URL.

Parameters:

settings (Settings) -- The package settings.

Returns:

A client; no connection is opened until the first command.

Return type:

Redis

class collective.redismemoize.client.Connection[source]#

Bases: object

A lazily created client and the circuit breaker in front of it.

Parameters:
  • settings -- The package settings.

  • factory -- Builds the client.

  • clock -- Monotonic clock, in seconds; injectable for tests.

__init__(settings, factory=<function default_factory>, clock=<built-in function monotonic>)[source]#
Parameters:
client()[source]#

Return the client for this process, creating it if needed.

Returns:

The client.

Return type:

Any

property is_open: bool#

Report whether the breaker is open, whatever the time.

Returns:

True from a failure until the next success.

seconds_until_retry()[source]#

Return how long the breaker keeps Redis out of reach.

Returns:

Seconds until the next attempt; 0 when closed or due.

Return type:

float

available()[source]#

Report whether Redis may be called now.

Returns:

False while the breaker waits out retry_after.

Return type:

bool

failure(exc)[source]#

Record a failed call, opening the breaker.

Parameters:

exc (BaseException) -- What went wrong, for the log.

Return type:

None

success()[source]#

Record a successful call, closing the breaker if it was open.

Return type:

None

collective.redismemoize.client.get_connection()[source]#

Return the process connection, matching the current settings.

Returns:

The connection; a new one when the settings were reloaded.

Return type:

Connection

collective.redismemoize.client.set_factory(factory)[source]#

Replace the client factory, and drop the current connection.

Parameters:

factory (Callable[[Settings], Any] | None) -- The new factory; None restores redis-py.

Return type:

None

collective.redismemoize.client.reset()[source]#

Drop the current connection; the next call creates a new one.

Return type:

None