Rindle.Storage.Local (Rindle v0.1.6)

Copy Markdown View Source

Local filesystem storage adapter.

Summary

Functions

Resolves a storage key to an expanded filesystem path under the configured root.

Returns the expanded local storage root for the given opts.

Appends chunk to the tus tmp part file for session_id.

Atomically finalizes the tus upload by renaming the tmp part into key.

Resolves the tus tmp part path for session_id under the configured root.

Functions

path_for(key, opts)

@spec path_for(
  String.t(),
  keyword()
) :: String.t()

Resolves a storage key to an expanded filesystem path under the configured root.

root(opts)

@spec root(keyword()) :: String.t()

Returns the expanded local storage root for the given opts.

tus_append(session_id, chunk, opts)

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

Appends chunk to the tus tmp part file for session_id.

Opens the part path in [:append, :binary] mode (creating the tus tmp directory if needed) and binary-writes the chunk. Returns :ok or a tagged error. Never buffers the whole upload — callers append per PATCH chunk.

tus_complete(session_id, key, opts)

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

Atomically finalizes the tus upload by renaming the tmp part into key.

Moves <root>/tus/<session_id>.part to the final storage path for key. Because both paths live under root/1 (same filesystem), File.rename/2 is atomic. A cross-device error (:exdev) is a misconfiguration (tmp dir and storage root on different filesystems) and is surfaced as an error — never a silent copy+delete fallback (Pitfall 5).

tus_part_path(session_id, opts)

@spec tus_part_path(
  String.t(),
  keyword()
) :: String.t()

Resolves the tus tmp part path for session_id under the configured root.

The part file lives at <root>/tus/<session_id>.part. session_id is always a server-issued identifier (UUID), so the path is structurally traversal-proof. Kept under root/1 so the completion File.rename/2 is an atomic same-filesystem rename (see tus_complete/3).