# Storage Backends Potable separates repository logic from storage implementation through behaviours. ## Block Store `Potable.BlockStore` is the required content-addressed storage interface used by `Potable.Repository`, `Potable.MST`, and `Potable.CAR`. ### Callbacks - `start_link(opts)` - `put(store, cid, bytes)` - `get(store, cid)` - `has?(store, cid)` - `delete(store, cid)` - `stat(store)` Batch helpers: - `put_many(store, [{cid, bytes}, ...])` - `get_many(store, [cid, ...])` ### Included Backend `Potable.BlockStore.Memory`: - GenServer + ETS-backed in-memory implementation - useful for tests and local experiments - idempotent CID writes ## Blob Storage Blob helpers are intentionally separated from block storage. ### `Potable.Blob` Struct representing AT blob envelope: - `ref` (`Potable.CID`) - `mime_type` - `size` Helpers: - `new/3` - `validate/2` - `to_map/1` - `from_map/1` ### `Potable.Blob.Storage` Behaviour - `put_blob(storage, blob, data, opts)` - `get_blob(storage, cid, opts)` - `delete_blob(storage, cid, opts)` (optional) - `blob_exists?(storage, cid, opts)` (optional) ### Included Blob Backend `Potable.Blob.MemoryStorage`: - Agent-backed map by CID string - test-oriented implementation ## Backend Adapter Pattern If your app stores blocks in Postgres, SQLite, S3, etc.: 1. implement a process (usually GenServer) that accepts Potable message shapes 2. convert `%Potable.CID{}` to native key form 3. delegate to your storage layer 4. normalize return values (`{:ok, bytes}` or `{:error, :not_found}`) Minimal skeleton: ```elixir defmodule MyApp.BlockAdapter do use GenServer alias Potable.CID def start_link(opts), do: GenServer.start_link(__MODULE__, opts) def init(opts), do: {:ok, opts} def handle_call({:get, %CID{} = cid}, _from, state) do cid_string = CID.cid_to_string(cid) reply = case MyStorage.get(cid_string) do {:ok, bytes} -> {:ok, bytes} :not_found -> {:error, :not_found} {:error, _} = err -> err end {:reply, reply, state} end end ``` See Roster's production adapter in `server/lib/roster/storage/blockstore_adapter.ex`.