Plain objects in the store a database lives in: small objects with
conditional writes (get/3, put/4), such as leases (see
Slap.Cluster.Strategy.ObjectLease), and large ones streamed in and out
(upload/4, download/3), such as file bodies. Every call takes the
:timeout option (see Slap.SlateDB); for a stream it bounds each step.
{:ok, store} = Slap.SlateDB.ObjectStore.open("_cluster", store: {:url, "s3://bucket/prefix"})
{:ok, version} = Slap.SlateDB.ObjectStore.put(store, "leases/0", "a", mode: :create)
{:ok, {"a", ^version}} = Slap.SlateDB.ObjectStore.get(store, "leases/0")
{:error, :conflict} = Slap.SlateDB.ObjectStore.put(store, "leases/0", "b", mode: :create)
{:ok, _} = Slap.SlateDB.ObjectStore.put(store, "leases/0", "b", mode: {:update, version})Conditional updates ({:update, version}, an If-Match PUT) need a store
that supports them: S3 and S3-compatible stores such as RustFS, Azure,
GCS, :memory, and local stores. Local mutations share one OS lock per
canonical store root, including across handles and processes. On a
filesystem without microsecond modification times, local updates return
:unsupported.
Local stores sync file contents before PUT or upload completion returns success. On Unix, they also sync directory changes for object creation and deletion. This can increase latency. Persistence requires the filesystem and device to honor sync requests; other platforms do not sync directory entries.
An atom error means the store refused a condition or does not support it;
%Slap.SlateDB.Error{} means the operation failed.
Summary
Functions
Deletes an object. Deleting one that does not exist is not an error.
Opens the object at key for reading. Returns {:ok, {chunks, size, version}}, where chunks is a lazy stream of binaries (reading it
raises Slap.SlateDB.Error if the store fails) and size is the size of
the whole object, or {:ok, nil} if there is no object.
The object's body and version, or {:ok, nil} if there is none.
The keys under prefix, in no particular order.
Opens store (as for Slap.SlateDB.open/2). Keys are relative to path
within it (and to the prefix of a store URL). The :store option is required.
Writes an object. :mode is
Writes the object at key from chunks, an enumerable of binaries, and
returns {:ok, version}. Nothing is visible at key until the whole body
is written.
Types
Functions
@spec delete(t(), String.t(), keyword()) :: :ok | {:error, Slap.SlateDB.Error.t()}
Deletes an object. Deleting one that does not exist is not an error.
@spec download(t(), String.t(), keyword()) :: {:ok, {Enumerable.t(), non_neg_integer(), version()} | nil} | {:error, Slap.SlateDB.Error.t()}
Opens the object at key for reading. Returns {:ok, {chunks, size, version}}, where chunks is a lazy stream of binaries (reading it
raises Slap.SlateDB.Error if the store fails) and size is the size of
the whole object, or {:ok, nil} if there is no object.
range: {first, last} reads only the bytes from first to last,
inclusive, as an HTTP range does. A last past the end of the object
reads to its end. A range that starts past the end returns an error whose
form depends on the store, so check the range against the object's size
first.
@spec get(t(), String.t(), keyword()) :: {:ok, {binary(), version()} | nil} | {:error, Slap.SlateDB.Error.t()}
The object's body and version, or {:ok, nil} if there is none.
@spec list(t(), String.t(), keyword()) :: {:ok, [String.t()]} | {:error, Slap.SlateDB.Error.t()}
The keys under prefix, in no particular order.
@spec open(String.t(), keyword()) :: {:ok, t()} | {:error, Slap.SlateDB.Error.t()}
Opens store (as for Slap.SlateDB.open/2). Keys are relative to path
within it (and to the prefix of a store URL). The :store option is required.
A :memory store is new and empty each time it is opened.
@spec put(t(), String.t(), binary(), keyword()) :: {:ok, version()} | {:error, :conflict | :unsupported | Slap.SlateDB.Error.t()}
Writes an object. :mode is:
:overwrite(default) - unconditionally.:create- only if there is no object atkey.{:update, version}- only if the object is still atversion.
Returns {:ok, version}, {:error, :conflict} when the condition does not
hold, or {:error, :unsupported} when the store cannot check it.
@spec upload(t(), String.t(), Enumerable.t(), keyword()) :: {:ok, version()} | {:error, Slap.SlateDB.Error.t()}
Writes the object at key from chunks, an enumerable of binaries, and
returns {:ok, version}. Nothing is visible at key until the whole body
is written.
A body smaller than one part (5 MiB) is written with a single PUT; a
larger one as a multipart upload, a few parts at a time, which is aborted
if chunks raises or the upload fails. A process that dies during an
upload leaves its parts behind until the store expires them (S3 needs a
lifecycle rule for incomplete multipart uploads).
On a local store, get/3 can briefly return an earlier version of key
just after an upload of it completes; conditional updates are not affected.
Use put/4 for objects whose versions you compare.