# Module Rpc_proxy.ReliabilityCache

    module ReliabilityCache: sig .. end

The reliability cache stores information about the availability of remote servers. The managed clients put information about recent failures into the cache.

It is advantegeous to have only one cache per process, because this maximizes the usefulness. The cache is thread-safe.

A server endpoint is disabled when too many errors occur in sequence. For a disabled endpoint the functions `host_is_enabled` and/or `sockaddr_is_enabled` return `false`. The endpoint is automatically enabled again after some timeout; this is initially `disable_timeout_min`, but is increased exponentially until `disable_timeout_max` when further errors occur.

Independently of this machinery the functions `host_is_enabled` and `sockaddr_is_enabled` may also return `false` when an external availability checker says that the endpoint is down. This information is not entered into the cache, and will also not trigger the disable timeout. Instead, the hook function getting the availability will be simply called again.

    type rcache

The cache

    type rcache_policy = [ `Any_failing_port_disables_host
           | `Failing_port_disables_host of int
           | `Independent
           | `None ]

How failures of individual ports are interpreted:

- ``Independent`: When a connection to a remote port repeatedly fails, only this port is disabled
- ``Failing_port_disables_host p`: When a connection to the TCP port `p` repeatedly fails, the whole remote host is disabled. Other ports do not disable the host, but are treated as in ``Independent`.
- ``Any_failing_port_disables_host`: When a connection to any TCP port repeatedly fails, the whole remote host is disabled
- ``None`: Nothing is disabled

Note that the `rcache_availability` hook is not affected by the policy; this hook is called anyway. The policy only determines how the internal error counter is interpreted.
`type ``rcache_config = {`

`` | `rcache_policy : `rcache_policy`;` | `(*` | The policy, see above | `*)`
`` | `rcache_disable_timeout_min : `float`;` | `(*` | For how long ports and hosts are disabled | `*)`
`` | `rcache_disable_timeout_max : `float`;` | `(*` | For how long ports and hosts are disabled at most | `*)`
`` | `rcache_threshold : `int`;` | `(*` | How many errors are required for disabling a port | `*)`
`` | `rcache_availability : `rcache -> Unix.sockaddr -> bool`;` | `(*` | External availability checker. Called by `sockaddr_is_enabled` before the result is calculated | `*)`

}

    val create_rcache_config : ?policy:rcache_policy ->
           ?disable_timeout_min:float ->
           ?disable_timeout_max:float ->
           ?threshold:int ->
           ?availability:(rcache -> Unix.sockaddr -> bool) ->
           unit -> rcache_config

Create a config record. The optional arguments set the config components with the same name. The arguments default to:

- `policy = `None`
- `disable_timeout_min = 1.0`
- `disable_timeout_max = 64.0`
- `threshold = 1`
- `availability = fun _ _ -> true`

    val create_rcache : rcache_config -> rcache

Creates a new cache object. The same cache can be used by several managed clients, even by totally unrelated ones

    val rcache_config : rcache -> rcache_config

Return the config

    val global_rcache_config : unit -> rcache_config

Returns the global config:

- `policy = `None`
- `disable_timeout_min = 1.0`
- `disable_timeout_max = 64.0`
- `threshold = 1`
- `availability = fun _ _ -> true`

    val set_global_rcache_config : rcache_config -> unit

Sets the new global config. This is only possible as long as neither `default_global_config` nor `global_rcache` have been called.

    val global_rcache : unit -> rcache

The global cache. Initially, this cache has the default config. It is possible to change the default config before using the global cache for the first time.

    val derive_rcache : rcache ->
           rcache_config -> rcache

`derive_cache parent config`: Returns a new cache that shares the error counters with `parent`. The interpretation of the counters, however, may be differently configured in `config`.

Because it is advantageous to share the error information as much as possible, the recommended way to create a new cache object is to derive it from the global cache.

What `derive_rcache` actually does (and this is not yet optimal): Any `incr` and `reset` of an error counter is also forwarded to the parent cache. The tests whether hosts and ports are enabled do an AND of the results for the cache and its parent (i.e. both must be ok to enable). This allows some information sharing, but only in vertical direction.

    val incr_rcache_error_counter : rcache -> Unix.sockaddr -> unit

Increase the error counter for this sockaddr. If the threshold is reached and there is a disable policy, the sockaddr will be disabled.

This function is to be called after an RPC call times out, or runs into a socket error.

    val reset_rcache_error_counter : rcache -> Unix.sockaddr -> unit

Reset the error counter for this sockaddr. If disabled, the sockaddr is set to enabled again.

This function is to be called when an RPC call is successful.

    val sockaddr_is_enabled : rcache -> Unix.sockaddr -> bool

Returns whether the sockaddr is enabled. This also calls the `rcache_availability` hook.

    val host_is_enabled : rcache -> Unix.inet_addr -> bool

Returns whether the host is enabled