khepri_cluster (khepri v0.6.0)

Khepri service and cluster management API.

This module provides the public API for the service and cluster management. For convenience, some functions of this API are repeated in the khepri module for easier access.

the-khepri-store-and-the-ra-cluster

The Khepri store and the Ra cluster

A Khepri store is a Ra server inside a Ra cluster. The Khepri store and the Ra cluster share the same name in fact. The only constraint is that the name must be an atom, even though Ra accepts other Erlang types as cluster names.

By default, Khepri uses khepri as the store ID (and thus Ra cluster name). This default can be overridden using an argument to the start/0 functions or the default_store_id application environment variable.

Examples:
  • Use the default Khepri store ID:
    {ok, khepri} = khepri:start().
  • Override the default store ID using an argument:
    {ok, my_store} = khepri:start("/var/lib/khepri", my_store).
  • Override the default store ID using an application environment variable:
    ok = application:set_env(
             khepri, default_store_id, my_store, [{persistent, true}]),
     
      {ok, my_store} = khepri:start().

the-data-directory-and-the-ra-system

The data directory and the Ra system

A Ra server relies on a Ra system to provide various functions and to configure the directory where the data should be stored on disk.

By default, Khepri will configure its own Ra system to write data under khepri in the current working directory, where Nodename is the name of the Erlang node.

  {ok, StoreId} = khepri:start().
 
  %% If the Erlang node was started without distribution (the default), the
  %% statement above will start a Ra system called like the store (`khepri')
  %% and will use the `khepri#nonode@nohost' directory.

The default data directory or Ra system name can be overridden using an argument to the start/0 or the default_ra_system application environment variable. Both a directory (string or binary) or the name of an already running Ra system are accepted.

Examples:
  • Override the default with the name of a running Ra system using an argument:
    {ok, StoreId} = khepri:start(my_ra_system).
  • Override the default data directory using an application environment variable:
    ok = application:set_env(
             khepri, default_ra_system, "/var/lib/khepri", [{persistent, true}]),
     
      {ok, StoreId} = khepri:start().

Please refer to Ra documentation to learn more about Ra systems and Ra clusters.

managing-ra-cluster-members

Managing Ra cluster members

A Khepri/Ra cluster can be expanded by telling a node to join a remote cluster. Note that the Khepri store/Ra server to add to the cluster must run before it can join.

  %% Start the local Khepri store.
  {ok, StoreId} = khepri:start().
 
  %% Join a remote cluster.
  ok = khepri_cluster:join(RemoteNode).

To remove the local Khepri store node from the cluster, it must be reset.

  %% Start the local Khepri store.
  ok = khepri_cluster:reset().

Link to this section Summary

Types

A Ra server config map.

Functions

Returns the default Ra system name or data directory.

Returns the default Khepri store ID.

Returns the list of running stores.
Indicates if StoreId is running or not.

Adds the local running Khepri store to a remote cluster.

Adds the local running Khepri store to a remote cluster.

Resets the store on this Erlang node.
Resets the store on this Erlang node.

Resets the store on this Erlang node.

Starts a store.

Starts a store.

Stops a store.

Stops a store.

Link to this section Types

Link to this type

incomplete_ra_server_config/0

-type incomplete_ra_server_config() :: map().

A Ra server config map.

This configuration map can lack the required parameters, Khepri will fill them if necessary. Important parameters for Khepri (e.g. machine) will be overridden anyway.

Link to this section Functions

Link to this function

cache_leader(StoreId, LeaderId)

-spec cache_leader(StoreId, LeaderId) -> ok
                when StoreId :: khepri:store_id(), LeaderId :: ra:server_id().
Link to this function

cache_leader_if_changed(StoreId, LeaderId, NewLeaderId)

-spec cache_leader_if_changed(StoreId, LeaderId, NewLeaderId) -> ok
                           when
                               StoreId :: khepri:store_id(),
                               LeaderId :: ra:server_id(),
                               NewLeaderId :: ra:server_id().
Link to this function

clear_cached_leader(StoreId)

-spec clear_cached_leader(StoreId) -> ok when StoreId :: khepri:store_id().
Link to this function

get_cached_leader(StoreId)

-spec get_cached_leader(StoreId) -> Ret
                     when
                         StoreId :: khepri:store_id(),
                         Ret :: LeaderId | undefined,
                         LeaderId :: ra:server_id().
Link to this function

get_default_ra_system_or_data_dir()

-spec get_default_ra_system_or_data_dir() -> RaSystem | DataDir
                                     when RaSystem :: atom(), DataDir :: file:filename_all().

Returns the default Ra system name or data directory.

This is based on Khepri's default_ra_system` application environment variable. The variable can be set to: <ul> <li>A directory (a string or binary) where data should be stored. A new Ra system called `khepri` will be initialized with this directory.</li> <li>A Ra system name (an atom). In this case, the user is expected to configure and start the Ra system before starting Khepri.</li> </ul> If this application environment variable is unset, the default is to configure a Ra system called `khepri which will write data in "khepri-$NODE" in the current working directory where $NODE is the Erlang node name.

Example of an Erlang configuration file for Khepri:
  {khepri, [{default_ra_system, "/var/db/khepri"}]}.
Link to this function

get_default_store_id()

-spec get_default_store_id() -> StoreId when StoreId :: khepri:store_id().

Returns the default Khepri store ID.

This is based on Khepri's default_store_id application environment variable. The variable can be set to an atom. The default is khepri.
Link to this function

get_store_ids()

-spec get_store_ids() -> [StoreId] when StoreId :: khepri:store_id().
Returns the list of running stores.
Link to this function

is_store_running(StoreId)

-spec is_store_running(StoreId) -> IsRunning when StoreId :: khepri:store_id(), IsRunning :: boolean().
Indicates if StoreId is running or not.
Link to this function

join(RemoteNode)

-spec join(RemoteMember | RemoteNode) -> Ret
        when RemoteMember :: ra:server_id(), RemoteNode :: node(), Ret :: ok | khepri:error().

Adds the local running Khepri store to a remote cluster.

This function accepts the following forms:
  • join(RemoteNode). Calling it is the same as calling join(DefaultStoreId, RemoteNode) where DefaultStoreId is returned by get_default_store_id/0.
  • join(RemoteMember). Calling it is the same as calling join(StoreId, RemoteNode) where StoreId and RemoteNode are derived from RemoteMember.

See also: join/2.

Link to this function

join(RemoteNode, Timeout)

-spec join(RemoteMember | RemoteNode | StoreId, Timeout | RemoteNode) -> Ret
        when
            RemoteMember :: ra:server_id(),
            RemoteNode :: node(),
            StoreId :: khepri:store_id(),
            Timeout :: timeout(),
            Ret :: ok | khepri:error().

Adds the local running Khepri store to a remote cluster.

This function accepts the following forms:
  • join(RemoteNode, Timeout). Calling it is the same as calling join(DefaultStoreId, RemoteNode, Timeout) where DefaultStoreId is returned by get_default_store_id/0.
  • join(StoreId, RemoteNode). Calling it is the same as calling join(StoreId, RemoteNode, DefaultTimeout) where DefaultTimeout is returned by khepri_app:get_default_timeout/0.
  • join(RemoteMember, Timeout). Calling it is the same as calling join(StoreId, RemoteNode, Timeout) where StoreId and RemoteNode are derived from RemoteMember.

See also: join/3.

Link to this function

locally_known_members(StoreId)

Link to this function

locally_known_members(StoreId, Timeout)

Link to this function

locally_known_nodes(StoreId)

Link to this function

members(StoreId)

Link to this function

members(StoreId, Timeout)

-spec reset() -> Ret when Ret :: ok | khepri:error().
Resets the store on this Erlang node.
-spec reset(StoreId | Timeout) -> Ret
         when StoreId :: khepri:store_id(), Timeout :: timeout(), Ret :: ok | khepri:error().
Resets the store on this Erlang node.
Link to this function

reset(StoreId, Timeout)

-spec reset(StoreId, Timeout) -> Ret
         when StoreId :: khepri:store_id(), Timeout :: timeout(), Ret :: ok | khepri:error().

Resets the store on this Erlang node.

It does that by force-deleting the Ra local server.

This function is also used to gracefully remove the local Khepri store node from a cluster.
-spec start() -> Ret when Ret :: khepri:ok(StoreId) | khepri:error(), StoreId :: khepri:store_id().

Starts a store.

Calling this function is the same as calling start(DefaultRaSystem) where DefaultRaSystem is returned by get_default_ra_system_or_data_dir/0.

See also: start/1, ra_server:ra_server_config().

Link to this function

start(RaSystemOrDataDir)

-spec start(RaSystem | DataDir) -> Ret
         when
             RaSystem :: atom(),
             DataDir :: file:filename_all(),
             Ret :: khepri:ok(StoreId) | khepri:error(),
             StoreId :: khepri:store_id().

Starts a store.

Calling this function is the same as calling start(RaSystemOrDataDir, DefaultStoreId) where DefaultStoreId is returned by get_default_store_id/0.

See also: start/2.

Link to this function

start(RaSystemOrDataDir, StoreIdOrRaServerConfig)

-spec start(RaSystem | DataDir, StoreId | RaServerConfig) -> Ret
         when
             RaSystem :: atom(),
             DataDir :: file:filename_all(),
             StoreId :: khepri:store_id(),
             RaServerConfig :: incomplete_ra_server_config(),
             Ret :: khepri:ok(StoreId) | khepri:error().

Starts a store.

Calling this function is the same as calling start(RaSystemOrDataDir, StoreIdOrRaServerConfig, DefaultTimeout) where DefaultTimeout is returned by khepri_app:get_default_timeout/0.

See also: start/3.

Link to this function

start(RaSystemOrDataDir, StoreIdOrRaServerConfig, Timeout)

-spec start(RaSystem | DataDir, StoreId | RaServerConfig, Timeout) -> Ret
         when
             RaSystem :: atom(),
             DataDir :: file:filename_all(),
             StoreId :: khepri:store_id(),
             RaServerConfig :: incomplete_ra_server_config(),
             Timeout :: timeout(),
             Ret :: khepri:ok(StoreId) | khepri:error().

Starts a store.

It accepts either a Ra system name (atom) or a data directory (string or binary) as its first argument. If a Ra system name is given, that Ra system must be running when this function is called. If a data directory is given, a new Ra system will be started, using this directory. The directory will be created automatically if it doesn't exist. The Ra system will use the same name as the Khepri store.

It accepts a Khepri store ID or a Ra server configuration as its second argument. If a store ID is given, a Ra server configuration will be created based on it. If a Ra server configuration is given, the name of the Khepri store will be derived from it.

If this is a new store, the Ra server is started and an election is triggered so that it becomes its own leader and is ready to process commands and queries.

If the store was started in the past and stopped, it will be restarted. In this case, RaServerConfig will be ignored. Ra will take care of the eletion automatically.
-spec stop() -> Ret when Ret :: ok | khepri:error().

Stops a store.

Calling this function is the same as calling stop(DefaultStoreId) where DefaultStoreId is returned by get_default_store_id/0.

See also: stop/1.

-spec stop(StoreId) -> Ret when StoreId :: khepri:store_id(), Ret :: ok | khepri:error().
Stops a store.