Arcadic (Arcadic v0.1.0)

Copy Markdown View Source

A lean, framework-agnostic Elixir client for ArcadeDB over the HTTP Cypher command API.

Arcadic is the "postgrex of ArcadeDB": it ships Cypher/SQL, manages connections and session transactions, and normalizes responses — nothing more. It is deliberately tenant-blind and framework-agnostic. Multitenancy, classification, and Ash resources live one layer up, in ash_arcadic.

conn = Arcadic.connect("http://localhost:2480", "mydb", auth: {"root", pass})
{:ok, rows} = Arcadic.query(conn, "MATCH (n:User) RETURN n LIMIT $lim", %{"lim" => 10})
{:ok, [user]} = Arcadic.command(conn, "CREATE (u:User {name:$n}) RETURN u", %{"n" => "Jo"})

{:ok, result} = Arcadic.transaction(conn, fn tx ->
  Arcadic.command!(tx, "MERGE (u:User {id:$id})", %{"id" => "u1"})
end)

All dynamic values reach ArcadeDB only as bound parameters ($name), never string interpolation.

Summary

Functions

Run a write statement (POST /api/v1/command). Returns {:ok, rows} or {:error, Arcadic.Error.t() | Arcadic.TransportError.t()}.

Run a write statement, returning the rows or raising.

Fire-and-forget write: sends awaitResponse: false; the server enqueues and returns HTTP 202. Returns :ok on enqueue — the caller CANNOT confirm the write landed (that is the defined semantic; use command/4 for confirmable writes).

Run a read statement (POST /api/v1/query). The server rejects non-idempotent statements. Returns {:ok, rows} or {:error, Arcadic.Error.t() | Arcadic.TransportError.t()}.

Run a read statement, returning the rows or raising.

Lazily stream a large read result as raw row maps (Bolt-only). Returns {:ok, Stream.t()} or {:error, %Arcadic.Error{reason: :not_supported}} when the transport has no cursor contract (HTTP) or the conn is inside a transaction.

Roll back the current transaction with a reason. See Arcadic.Transaction.rollback/2.

Run a function within a session transaction. See Arcadic.Transaction.transaction/3.

Derive a same-pool handle on another database. See Arcadic.Conn.with_database/2.

Functions

command(conn, statement, params \\ %{}, opts \\ [])

@spec command(Arcadic.Conn.t(), String.t(), map(), keyword()) ::
  {:ok, [map()]} | {:error, Exception.t()}

Run a write statement (POST /api/v1/command). Returns {:ok, rows} or {:error, Arcadic.Error.t() | Arcadic.TransportError.t()}.

command!(conn, statement, params \\ %{}, opts \\ [])

@spec command!(Arcadic.Conn.t(), String.t(), map(), keyword()) :: [map()]

Run a write statement, returning the rows or raising.

command_async(conn, statement, params \\ %{}, opts \\ [])

@spec command_async(Arcadic.Conn.t(), String.t(), map(), keyword()) ::
  :ok | {:error, Exception.t()}

Fire-and-forget write: sends awaitResponse: false; the server enqueues and returns HTTP 202. Returns :ok on enqueue — the caller CANNOT confirm the write landed (that is the defined semantic; use command/4 for confirmable writes).

connect(base_url, database, opts \\ [])

@spec connect(String.t(), String.t(), keyword()) :: Arcadic.Conn.t()

Build a connection handle. See Arcadic.Conn.new/3.

query(conn, statement, params \\ %{}, opts \\ [])

@spec query(Arcadic.Conn.t(), String.t(), map(), keyword()) ::
  {:ok, [map()]} | {:error, Exception.t()}

Run a read statement (POST /api/v1/query). The server rejects non-idempotent statements. Returns {:ok, rows} or {:error, Arcadic.Error.t() | Arcadic.TransportError.t()}.

query!(conn, statement, params \\ %{}, opts \\ [])

@spec query!(Arcadic.Conn.t(), String.t(), map(), keyword()) :: [map()]

Run a read statement, returning the rows or raising.

query_stream(conn, statement, params \\ %{}, opts \\ [])

@spec query_stream(Arcadic.Conn.t(), String.t(), map(), keyword()) ::
  {:ok, Enumerable.t()} | {:error, Arcadic.Error.t()}

Lazily stream a large read result as raw row maps (Bolt-only). Returns {:ok, Stream.t()} or {:error, %Arcadic.Error{reason: :not_supported}} when the transport has no cursor contract (HTTP) or the conn is inside a transaction.

Enumerating the stream opens a dedicated connection for its lifetime and pulls :chunk_size rows per round-trip (default 1000). :timeout bounds each RUN and PULL receive (default :infinity; set it to bound a stalled server) — a breach raises %Arcadic.TransportError{reason: :timeout}. Any protocol error mid-stream RAISES a typed error; the connection is always torn down on completion, early halt, or error.

rollback(tx, reason)

@spec rollback(Arcadic.Conn.t(), term()) :: no_return()

Roll back the current transaction with a reason. See Arcadic.Transaction.rollback/2.

transaction(conn, fun, opts \\ [])

@spec transaction(Arcadic.Conn.t(), (Arcadic.Conn.t() -> result), keyword()) ::
  {:ok, result} | {:error, term()}
when result: var

Run a function within a session transaction. See Arcadic.Transaction.transaction/3.

with_database(conn, database)

@spec with_database(Arcadic.Conn.t(), String.t()) :: Arcadic.Conn.t()

Derive a same-pool handle on another database. See Arcadic.Conn.with_database/2.