barrel_history (barrel_docdb v1.0.0)

View Source

barrel_history - Retained history log

An append-only, HLC-ordered log of every write a database applies: local writes, replicated versions (including losing conflict siblings), and conflict resolutions. One entry per write, keyed by the change-sequence HLC and written in the same atomic batch as the document, so the log never disagrees with the store.

Entries carry identity only (doc id, version, deleted, cause, version vector), never bodies: bodies resolve through the current body or the version-keyed archive, and stay resolvable within the retention window. The live changes feed is unaffected and keeps its one-entry-per-doc invariant.

Reads run in the caller's process against the store ref (pure RocksDB range scans), like barrel_docdb_reader.

Summary

Functions

Decode a history entry value (without the key's HLC).

Encode a history entry value.

Encode a history entry value with an optional encoded provenance blob.

Fold over history entries in HLC order.

Fold over history entries in HLC order with options: - from: first HLC to include (default: everything retained) - to: last HLC to include - limit: max entries to visit

Every version of a document still resolvable: the current winner plus the version chain (conflict and superseded siblings), newest first by version. Each item: #{version, status (current | conflict | superseded), deleted, vv}.

The body of one version of a document: the current body when the token is the winner, the version-keyed archive otherwise. Bodies of swept versions are gone ({error, not_found}), and a token that does not parse is not found either (this path serves user-supplied tokens over REST and MCP).

The oldest HLC the history is complete from, advanced by the retention sweeper. undefined until a sweep runs (history complete since database creation).

The history put for one applied write. Appended to the same WriteBatch as the entity/feed ops by the database writer. VV is the vector recorded with the write (the state after a winning write, the sibling's own vector for a losing one).

Like write_ops/7 with an encoded provenance blob (see barrel_provenance) recorded in the entry, or undefined.

Types

att_info/0

-type att_info() ::
          #{name := binary(),
            content_type := binary(),
            length := non_neg_integer(),
            digest := binary(),
            chunked => boolean(),
            chunk_size => pos_integer(),
            chunk_count => pos_integer()}.

cause/0

-type cause() :: local | replicated | resolve.

change/0

-type change() :: map().

db_config/0

-type db_config() :: #{path => string(), store => module(), atom() => term()}.

db_name/0

-type db_name() :: binary().

db_ref/0

-type db_ref() :: pid() | atom().

doc/0

-type doc() :: #{binary() => term()}.

doc_info/0

-type doc_info() :: #{id := docid(), rev := revid(), deleted := boolean(), revtree := revtree()}.

docid/0

-type docid() :: binary().

endpoint/0

-type endpoint() :: db_name() | {node(), db_name()} | {module(), term()}.

entry/0

-type entry() ::
          #{hlc := barrel_hlc:timestamp(),
            id := docid(),
            version := binary(),
            deleted := boolean(),
            cause := cause(),
            vv := barrel_vv:vv(),
            provenance => barrel_provenance:provenance()}.

rep_options/0

-type rep_options() ::
          #{continuous => boolean(),
            since => seq_string(),
            filter => fun((doc()) -> boolean()),
            atom() => term()}.

rev_info/0

-type rev_info() ::
          #{id := revid(),
            parent := revid() | undefined,
            deleted := boolean(),
            attachments => #{binary() => att_info()}}.

revid/0

-type revid() :: binary().

revtree/0

-type revtree() :: #{revid() => rev_info()}.

seq/0

-type seq() :: barrel_hlc:timestamp().

seq_string/0

-type seq_string() :: binary().

view_name/0

-type view_name() :: binary().

view_result/0

-type view_result() :: #{key := term(), value := term(), id := docid()}.

Functions

decode_entry(_)

-spec decode_entry(binary()) -> map().

Decode a history entry value (without the key's HLC).

encode_entry(DocId, Version, Deleted, Cause, VV)

-spec encode_entry(docid(), barrel_version:version(), boolean(), cause(), barrel_vv:vv()) -> binary().

Encode a history entry value.

encode_entry(DocId, Version, Deleted, Cause, VV, Prov)

-spec encode_entry(docid(),
                   barrel_version:version(),
                   boolean(),
                   cause(),
                   barrel_vv:vv(),
                   binary() | undefined) ->
                      binary().

Encode a history entry value with an optional encoded provenance blob.

fold(StoreRef, DbName, Fun, Acc)

-spec fold(barrel_store_rocksdb:db_ref(),
           db_name(),
           fun((entry(), term()) -> {ok, term()} | {stop, term()}),
           term()) ->
              term().

Fold over history entries in HLC order.

fold(StoreRef, DbName0, Fun, Acc, Opts)

-spec fold(barrel_store_rocksdb:db_ref(),
           db_name(),
           fun((entry(), term()) -> {ok, term()} | {stop, term()}),
           term(),
           map()) ->
              term().

Fold over history entries in HLC order with options: - from: first HLC to include (default: everything retained) - to: last HLC to include - limit: max entries to visit

get_doc_versions(StoreRef, DbName0, DocId)

-spec get_doc_versions(barrel_store_rocksdb:db_ref(), db_name(), docid()) ->
                          {ok, [map()]} | {error, not_found}.

Every version of a document still resolvable: the current winner plus the version chain (conflict and superseded siblings), newest first by version. Each item: #{version, status (current | conflict | superseded), deleted, vv}.

get_version_body(StoreRef, DbName0, DocId, VersionToken)

-spec get_version_body(barrel_store_rocksdb:db_ref(), db_name(), docid(), binary()) ->
                          {ok, map()} | {error, not_found}.

The body of one version of a document: the current body when the token is the winner, the version-keyed archive otherwise. Bodies of swept versions are gone ({error, not_found}), and a token that does not parse is not found either (this path serves user-supplied tokens over REST and MCP).

history_floor(StoreRef, DbName0)

-spec history_floor(barrel_store_rocksdb:db_ref(), db_name()) -> barrel_hlc:timestamp() | undefined.

The oldest HLC the history is complete from, advanced by the retention sweeper. undefined until a sweep runs (history complete since database creation).

write_ops(DbName, ChangeHlc, DocId, Version, Deleted, Cause, VV)

The history put for one applied write. Appended to the same WriteBatch as the entity/feed ops by the database writer. VV is the vector recorded with the write (the state after a winning write, the sibling's own vector for a losing one).

write_ops(DbName, ChangeHlc, DocId, Version, Deleted, Cause, VV, Prov)

-spec write_ops(db_name(),
                barrel_hlc:timestamp(),
                docid(),
                barrel_version:version(),
                boolean(),
                cause(),
                barrel_vv:vv(),
                binary() | undefined) ->
                   [term()].

Like write_ops/7 with an encoded provenance blob (see barrel_provenance) recorded in the entry, or undefined.