ExStorageService.BlobStore.LocalCAS (ex_storage_service v0.6.2)

Copy Markdown View Source

Durable local content-addressed blob storage.

Staging and ready files default to directories below the same cas root. Commit syncs staged bytes, closes the file, atomically renames it, and syncs both directories affected by the rename where the platform supports directory handles. The configured staging and ready roots must share a filesystem; a cross-device rename is rejected without copying or publishing partial content.

Filesystem operations and boundary faults are injectable per call through :fs_module and :faults; no mutable global test state is used.

Summary

Functions

Publishes a checksum-verified repair, atomically replacing a corrupt path.

Ensures a hash is ready in the global CAS.

Stages bytes from a state-threaded reader without buffering the full body.

Validates a bare hexadecimal SHA-256 digest without raising.

Types

reader_result(state)

@type reader_result(state) ::
  {:more, binary(), state}
  | {:ok, binary(), state}
  | {:done, state}
  | {:error, term()}
  | {:error, term(), state}

Functions

commit_repair(staged, opts \\ [])

@spec commit_repair(
  ExStorageService.BlobStore.StagedBlob.t(),
  keyword()
) :: {:ok, ExStorageService.BlobStore.ReadyBlob.t()} | {:error, term()}

Publishes a checksum-verified repair, atomically replacing a corrupt path.

The staged source is independently verified before the final same-filesystem rename. POSIX rename replacement keeps readers on either the old inode or the complete repaired inode; no partial destination is exposed.

ensure_ready(hash, opts \\ [])

@spec ensure_ready(
  String.t(),
  keyword()
) :: {:ok, map()} | {:error, term()}

Ensures a hash is ready in the global CAS.

Existing loose or packed blobs are returned unchanged. With :bucket, legacy content is streamed for checksum verification, synced, and renamed into the CAS using the normal durable commit path.

stage_from_reader(reader, initial_state, opts \\ [])

@spec stage_from_reader((state -> reader_result(state)), state, keyword()) ::
  {:ok, ExStorageService.BlobStore.StagedBlob.t(), state}
  | {:error, term(), state}
when state: term()

Stages bytes from a state-threaded reader without buffering the full body.

The reader receives its current state and must return {:more, chunk, state} while data remains, or {:ok, final_chunk, state} / {:done, state} when complete. The final reader state is returned to callers so adapters retain updates such as a consumed Plug.Conn.

:max_size defaults to the configured maximum object size. Reader, write, and size-limit failures close and remove the partial staging file.

validate_hash(hash)

@spec validate_hash(term()) :: :ok | {:error, :invalid_hash}

Validates a bare hexadecimal SHA-256 digest without raising.