Bedrock.Internal.Repo (bedrock v0.7.0)

View Source

Summary

Types

key()

@type key() :: term()

transaction()

@type transaction() :: pid()

value()

@type value() :: term()

Functions

add_read_conflict_key(repo_module, key)

@spec add_read_conflict_key(module(), key()) :: :ok

add_write_conflict_range(repo_module, start_key, end_key)

@spec add_write_conflict_range(module(), key(), key()) :: :ok

atomic(repo_module, op, key, value)

@spec atomic(module(), atom(), key(), binary()) :: :ok

clear(repo_module, key, opts \\ [])

@spec clear(module(), key(), opts :: [{:no_write_conflict, boolean()}]) :: :ok

clear_range(repo_module, start_key, end_key, opts \\ [])

@spec clear_range(
  module(),
  start_key :: key(),
  end_key :: key(),
  opts :: [{:no_write_conflict, boolean()}]
) :: :ok

get(repo_module, key)

@spec get(module(), key()) :: nil | value()

get(repo_module, key, opts)

@spec get(module(), key(), opts :: keyword()) :: nil | value()

get_range(repo_module, start_key, end_key)

@spec get_range(module(), start_key :: key(), end_key :: key()) ::
  Enumerable.t({any(), any()})

Create a lazy stream for a range query.

Options

  • :batch_size - Number of items to fetch per batch (default: 100)
  • :timeout - Timeout per batch request (default: 5000)
  • :limit - Maximum total items to return

get_range(repo_module, start_key, end_key, opts)

@spec get_range(
  module(),
  start_key :: key(),
  end_key :: key(),
  opts :: [
    batch_size: pos_integer(),
    timeout: pos_integer(),
    limit: pos_integer(),
    mode: :individual | :batch,
    snapshot: boolean()
  ]
) :: Enumerable.t({any(), any()})

put(repo_module, key, value, opts \\ [])

@spec put(module(), key(), value(), opts :: [{:no_write_conflict, boolean()}]) :: :ok

retry_delay_in_ms(retry_count)

@spec retry_delay_in_ms(non_neg_integer()) :: pos_integer()

The delay before retry number retry_count, in milliseconds.

FULL JITTER: a uniform draw from the whole interval below a ceiling that doubles, capped. The ceiling schedule is unchanged — what changed is that the delay is drawn from ALL of it rather than from a 3ms band at the top.

That distinction is the whole point. Transactions contending on one key fail at nearly the same instant; if they then compute nearly the same delay they wake together and collide again, and the round trip repeats at twice the delay. Spreading them across the interval means some contender arrives while the key is uncontended instead of every contender re-colliding. Identical 100-way workloads varied 278ms to 2059ms on the old schedule.

This is FDB's client backoff (NativeAPI.actor.cpp:4436: returnedBackoff *= deterministicRandom()->random01(), with the ceiling grown at :4446 by BACKOFF_GROWTH_RATE). Never zero, so a retry can never become a spin.

rollback(reason)

@spec rollback(reason :: term()) :: no_return()

select(repo_module, key_selector)

@spec select(module(), Bedrock.KeySelector.t()) ::
  nil | {resolved_key :: key(), value()}

select(repo_module, key_selector, opts)

@spec select(module(), Bedrock.KeySelector.t(), opts :: keyword()) ::
  nil | {resolved_key :: key(), value()}

transact(cluster, repo, fun, opts \\ [])

@spec transact(
  cluster :: module(),
  repo :: module(),
  (-> result) | (module() -> result),
  opts :: keyword()
) :: result
when result: any()

Executes a function within a transaction context with automatic retry logic.

Options

  • :retry_limit - Maximum number of retry attempts (default: unlimited)
  • :timeout_in_ms - End-to-end transaction timeout, including retries (default: 5000; use :infinity to disable)
  • :transaction_system_layout - Use a specific TSL instead of fetching from coordinator