Elixir Client
Official SDK
v0.1.0
Elixir 1.14+ / OTP 25+
Getting Started
Installation
Add to your mix.exs dependencies:
defp deps do
[
{:solidb, "~> 0.1.0"}
]
end
Then run:
mix deps.get
Requirements: Elixir 1.14+ and OTP 25+. The client uses msgpax for MessagePack serialization.
Quick Start
# Create and connect
{:ok, client} = SoliDB.Client.connect("127.0.0.1", 6745)
# Authenticate
:ok = SoliDB.Client.auth(client, "_system", "admin", "password")
# Set database context (required for management modules)
client = SoliDB.Client.use_database(client, "mydb")
# Basic CRUD operations
{:ok, doc} = SoliDB.Client.insert(client, "mydb", "users", %{name: "Alice", age: 30})
IO.puts("Created: #{doc["_key"]}")
{:ok, user} = SoliDB.Client.get(client, "mydb", "users", doc["_key"])
IO.puts("Retrieved: #{user["name"]}")
:ok = SoliDB.Client.update(client, "mydb", "users", doc["_key"], %{age: 31})
# Query with SDBQL
{:ok, results} = SoliDB.Client.query(client, "mydb", "FOR u IN users FILTER u.age > @min RETURN u", %{min: 25})
IO.puts("Found #{length(results)} users")
# Use management modules (functional style)
{:ok, scripts} = SoliDB.Scripts.list(client)
{:ok, triggers} = SoliDB.Triggers.list(client)
# Clean up
SoliDB.Client.close(client)
Connection Management
# Connect to SoliDB server
{:ok, client} = SoliDB.Client.connect("127.0.0.1", 6745)
# Check connection latency (returns ms)
{:ok, latency} = SoliDB.Client.ping(client)
IO.puts("Latency: #{Float.round(latency, 2)}ms")
# Close connection when done
SoliDB.Client.close(client)
| Function | Returns | Description |
|---|---|---|
connect(host, port) | {:ok, client} | Establish TCP connection |
ping(client) | {:ok, float} | Latency in milliseconds |
close(client) | :ok | Close connection |
use_database(client, name) | client | Set database context for modules |
Authentication
# Authenticate with database, username, and password
:ok = SoliDB.Client.auth(client, "_system", "admin", "password")
# Authentication is required for most operations
# The session remains authenticated until disconnected
Core Operations
Database Operations
# List all databases
{:ok, databases} = SoliDB.Client.list_databases(client)
# => ["_system", "mydb", "testdb"]
# Create a new database
:ok = SoliDB.Client.create_database(client, "analytics")
# Delete a database
:ok = SoliDB.Client.delete_database(client, "old_db")
| Function | Returns | Description |
|---|---|---|
list_databases(client) | {:ok, list} | List all database names |
create_database(client, name) | :ok | Create new database |
delete_database(client, name) | :ok | Delete database |
Collection Operations
# List collections in a database
{:ok, collections} = SoliDB.Client.list_collections(client, "mydb")
# => [%{"name" => "users", "type" => "document"}, ...]
# Create a document collection
:ok = SoliDB.Client.create_collection(client, "mydb", "products")
# Create an edge collection (for graphs)
:ok = SoliDB.Client.create_collection(client, "mydb", "relationships", "edge")
# Get collection statistics
{:ok, stats} = SoliDB.Client.collection_stats(client, "mydb", "users")
# => %{"count" => 1523, "size" => 245760, ...}
# Delete a collection
:ok = SoliDB.Client.delete_collection(client, "mydb", "old_collection")
| Function | Returns | Description |
|---|---|---|
list_collections(client, db) | {:ok, list} | List collections in database |
create_collection(client, db, name, type \\\\ nil) | :ok | Create collection (type: document/edge) |
collection_stats(client, db, name) | {:ok, map} | Get collection statistics |
delete_collection(client, db, name) | :ok | Delete collection |
Document Operations (CRUD)
# INSERT - Create a new document
{:ok, doc} = SoliDB.Client.insert(client, "mydb", "users", %{
name: "Alice",
email: "[email protected]",
age: 30
})
IO.puts(doc["_key"]) # Auto-generated key
# INSERT with custom key
{:ok, doc} = SoliDB.Client.insert(client, "mydb", "users", %{name: "Bob"}, "custom-key-123")
# GET - Retrieve a document by key
{:ok, user} = SoliDB.Client.get(client, "mydb", "users", "custom-key-123")
# => %{"_key" => "custom-key-123", "name" => "Bob", ...}
# UPDATE - Modify a document (merge by default)
:ok = SoliDB.Client.update(client, "mydb", "users", "custom-key-123", %{age: 25})
# UPDATE - Replace entire document (merge: false)
:ok = SoliDB.Client.update(client, "mydb", "users", "custom-key-123", %{name: "Robert"}, false)
# DELETE - Remove a document
:ok = SoliDB.Client.delete(client, "mydb", "users", "custom-key-123")
# LIST - Paginated document listing
{:ok, docs} = SoliDB.Client.list(client, "mydb", "users", 50, 0) # limit: 50, offset: 0
| Function | Returns | Description |
|---|---|---|
insert(client, db, col, doc, key \\\\ nil) | {:ok, map} | Insert document, returns doc with _key |
get(client, db, col, key) | {:ok, map} | Get document by key |
update(client, db, col, key, doc, merge \\\\ true) | :ok | Update document (merge or replace) |
delete(client, db, col, key) | :ok | Delete document |
list(client, db, col, limit \\\\ 50, offset \\\\ 0) | {:ok, list} | List documents with pagination |
SDBQL Queries
# Simple query
{:ok, users} = SoliDB.Client.query(client, "mydb", "FOR u IN users RETURN u")
# Query with bind variables (recommended for security)
{:ok, results} = SoliDB.Client.query(client, "mydb", """
FOR u IN users
FILTER u.age >= @min_age AND u.status == @status
SORT u.created_at DESC
LIMIT @limit
RETURN {name: u.name, email: u.email}
""", %{
min_age: 18,
status: "active",
limit: 100
})
# Aggregation query
{:ok, stats} = SoliDB.Client.query(client, "mydb", """
FOR u IN users
COLLECT status = u.status WITH COUNT INTO count
RETURN {status, count}
""")
# Join query
{:ok, orders} = SoliDB.Client.query(client, "mydb", """
FOR o IN orders
FOR u IN users FILTER u._key == o.user_id
RETURN {order: o, user: u.name}
""")
# Explain query plan (for optimization)
{:ok, plan} = SoliDB.Client.explain(client, "mydb", "FOR u IN users FILTER u.age > 25 RETURN u")
ACID Transactions
# Begin a transaction
{:ok, tx_id} = SoliDB.Client.begin_transaction(client, "mydb", "read_committed")
# Isolation levels: read_uncommitted, read_committed, repeatable_read, serializable
try do
# Perform operations within transaction
{:ok, _} = SoliDB.Client.insert(client, "mydb", "accounts", %{id: 1, balance: 1000})
{:ok, _} = SoliDB.Client.insert(client, "mydb", "accounts", %{id: 2, balance: 500})
# Commit if all operations succeed
:ok = SoliDB.Client.commit_transaction(client, tx_id)
IO.puts("Transaction committed")
rescue
error ->
# Rollback on any error
SoliDB.Client.rollback_transaction(client, tx_id)
IO.puts("Transaction rolled back: #{inspect(error)}")
end
| Function | Returns | Description |
|---|---|---|
begin_transaction(client, db, isolation \\\\ nil) | {:ok, string} | Start transaction, returns tx_id |
commit_transaction(client, tx_id) | :ok | Commit transaction |
rollback_transaction(client, tx_id) | :ok | Rollback transaction |
Index Management
# Create an index
:ok = SoliDB.Client.create_index(client, "mydb", "users", "idx_email", ["email"], true, false)
# client db col name fields unique sparse
# List indexes on a collection
{:ok, indexes} = SoliDB.Client.list_indexes(client, "mydb", "users")
# Delete an index
:ok = SoliDB.Client.delete_index(client, "mydb", "users", "idx_email")
Management Modules
Elixir uses a functional approach with separate modules instead of sub-clients.
Important: Call use_database(client, name) first to set the database context.
SoliDB.Scripts
Lua Script Endpointsclient = SoliDB.Client.use_database(client, "mydb")
# Create a Lua script endpoint
{:ok, script} = SoliDB.Scripts.create(client,
name: "hello",
path: "/api/hello",
methods: ["GET", "POST"],
code: ~s(return {message = "Hello, " .. (req.params.name or "World")}),
description: "Greeting endpoint", # optional
collection: "users" # optional: restrict to collection
)
IO.puts("Created script: #{script["_key"]}")
# List all scripts
{:ok, scripts} = SoliDB.Scripts.list(client)
Enum.each(scripts, fn s -> IO.puts("#{s["name"]} -> #{s["path"]}") end)
# Get a specific script
{:ok, script} = SoliDB.Scripts.get(client, "script_key")
# Update script code
:ok = SoliDB.Scripts.update(client, "script_key", %{
code: ~s(return {message = "Updated!"}),
methods: ["GET"]
})
# Delete a script
:ok = SoliDB.Scripts.delete(client, "script_key")
# Get execution statistics
{:ok, stats} = SoliDB.Scripts.get_stats(client)
IO.puts("Total calls: #{stats["total_calls"]}")
| Function | Parameters | Description |
|---|---|---|
create(client, opts) | name:, path:, methods:, code:, description:, collection: | Create Lua endpoint |
list(client) | - | List all scripts |
get(client, script_id) | script_id | Get script details |
update(client, script_id, updates) | script_id, map | Update script properties |
delete(client, script_id) | script_id | Delete script |
get_stats(client) | - | Execution statistics |
SoliDB.Jobs & SoliDB.Cron
Background Processingclient = SoliDB.Client.use_database(client, "mydb")
# === JOBS ===
# List all queues
{:ok, queues} = SoliDB.Jobs.list_queues(client)
# => [%{"name" => "default", "pending" => 5, "running" => 2}, ...]
# List jobs in a queue with filters
{:ok, jobs} = SoliDB.Jobs.list_jobs(client, "default",
status: "pending", # pending, running, completed, failed
limit: 50,
offset: 0
)
# Enqueue a new job
{:ok, job} = SoliDB.Jobs.enqueue(client, "default",
script_path: "/scripts/process-order",
params: %{order_id: 12345},
priority: 10, # optional: higher = more urgent
run_at: nil # optional: ISO8601 datetime for delayed execution
)
IO.puts("Job ID: #{job["_key"]}")
# Get job details
{:ok, job} = SoliDB.Jobs.get(client, "job_id")
IO.puts("Status: #{job["status"]}")
# Cancel a pending job
:ok = SoliDB.Jobs.cancel(client, "job_id")
# === CRON ===
# List scheduled jobs
{:ok, crons} = SoliDB.Cron.list(client)
# Create a cron job
{:ok, cron} = SoliDB.Cron.create(client,
name: "daily-cleanup",
schedule: "0 2 * * *", # Every day at 2 AM
script_path: "/scripts/cleanup",
params: %{days_old: 30}, # optional
enabled: true, # optional
description: "Remove old records" # optional
)
# Get cron job details
{:ok, cron} = SoliDB.Cron.get(client, "cron_id")
# Update cron schedule
:ok = SoliDB.Cron.update(client, "cron_id", %{schedule: "0 3 * * *"})
# Toggle cron job on/off
:ok = SoliDB.Cron.toggle(client, "cron_id", false) # disable
:ok = SoliDB.Cron.toggle(client, "cron_id", true) # enable
# Delete cron job
:ok = SoliDB.Cron.delete(client, "cron_id")
SoliDB.Triggers
Database Triggersclient = SoliDB.Client.use_database(client, "mydb")
# List all triggers
{:ok, triggers} = SoliDB.Triggers.list(client)
# List triggers for a specific collection
{:ok, triggers} = SoliDB.Triggers.list_by_collection(client, "users")
# Create a trigger
{:ok, trigger} = SoliDB.Triggers.create(client,
name: "on_user_created",
collection: "users",
event: "insert", # insert, update, delete
timing: "after", # before, after
script_path: "/scripts/on-user-create",
enabled: true # optional
)
# Get trigger details
{:ok, trigger} = SoliDB.Triggers.get(client, "trigger_id")
# Update trigger
:ok = SoliDB.Triggers.update(client, "trigger_id", %{
script_path: "/scripts/new-handler",
enabled: false
})
# Toggle trigger on/off
:ok = SoliDB.Triggers.toggle(client, "trigger_id", true) # enable
:ok = SoliDB.Triggers.toggle(client, "trigger_id", false) # disable
# Delete trigger
:ok = SoliDB.Triggers.delete(client, "trigger_id")
| Event | Timing | Description |
|---|---|---|
insert | before / after | Fires on document creation |
update | before / after | Fires on document modification |
delete | before / after | Fires on document removal |
SoliDB.Roles & SoliDB.Users
Role-Based Access Control# === ROLES ===
# List all roles
{:ok, roles} = SoliDB.Roles.list(client)
# Create a role with permissions
{:ok, role} = SoliDB.Roles.create(client,
name: "editor",
permissions: [
%{action: "read", scope: "database", database: "mydb"},
%{action: "write", scope: "collection", database: "mydb", collection: "articles"},
%{action: "execute", scope: "script", database: "mydb"}
],
description: "Content editor role"
)
# Get role details
{:ok, role} = SoliDB.Roles.get(client, "editor")
# Update role permissions
:ok = SoliDB.Roles.update(client, "editor", %{
permissions: [
%{action: "read", scope: "database", database: "mydb"},
%{action: "write", scope: "database", database: "mydb"}
]
})
# Delete role
:ok = SoliDB.Roles.delete(client, "editor")
# === USERS ===
# List all users
{:ok, users} = SoliDB.Users.list(client)
# Create a user
{:ok, user} = SoliDB.Users.create(client,
username: "john",
password: "secure_password",
roles: ["editor", "viewer"] # optional
)
# Get user details
{:ok, user} = SoliDB.Users.get(client, "john")
# Get user's assigned roles
{:ok, roles} = SoliDB.Users.get_roles(client, "john")
# Assign a role to user
:ok = SoliDB.Users.assign_role(client, "john", "admin", database: "mydb")
# Revoke a role from user
:ok = SoliDB.Users.revoke_role(client, "john", "admin", database: "mydb")
# Get current authenticated user
{:ok, me} = SoliDB.Users.me(client)
# Get current user's permissions
{:ok, permissions} = SoliDB.Users.my_permissions(client)
# Change password
:ok = SoliDB.Users.change_password(client, "john", "old_password", "new_password")
# Delete user
:ok = SoliDB.Users.delete(client, "john")
| Action | Scopes | Description |
|---|---|---|
read | database, collection | Read documents and query |
write | database, collection | Create, update, delete documents |
admin | database, collection | Manage indexes, schema, etc. |
execute | script | Execute Lua scripts |
Advanced Features
SoliDB.Vector
Vector Search & AIclient = SoliDB.Client.use_database(client, "mydb")
# Create a vector index
{:ok, index} = SoliDB.Vector.create_index(client, "products",
name: "product_embeddings",
field: "embedding",
dimensions: 1536,
metric: "cosine" # cosine, euclidean, dot_product
)
# Search by vector (semantic search)
embedding = get_embedding("wireless headphones") # Your embedding function
{:ok, results} = SoliDB.Vector.search(client, "products",
vector: embedding,
limit: 10,
filter: ~s(doc.category == "electronics") # optional SDBQL filter
)
Enum.each(results, fn result ->
IO.puts("#{result["doc"]["name"]} - Score: #{result["score"]}")
end)
# Search by existing document (find similar)
{:ok, similar} = SoliDB.Vector.search_by_document(client, "products",
doc_key: "product-123",
field: "embedding",
limit: 5
)
# Quantize index (reduce memory usage)
:ok = SoliDB.Vector.quantize(client, "products", "product_embeddings", "binary")
# Dequantize (restore full precision)
:ok = SoliDB.Vector.dequantize(client, "products", "product_embeddings")
# Get index info
{:ok, info} = SoliDB.Vector.get_index_info(client, "products", "product_embeddings")
# List vector indexes
{:ok, indexes} = SoliDB.Vector.list_indexes(client, "products")
# Delete index
:ok = SoliDB.Vector.delete_index(client, "products", "product_embeddings")
SoliDB.Geo
Geospatial Queriesclient = SoliDB.Client.use_database(client, "mydb")
# Create a geo index
:ok = SoliDB.Geo.create_index(client, "stores",
name: "location_idx",
fields: ["location"], # Field containing [lat, lon] or GeoJSON
geo_json: true # optional: true if using GeoJSON format
)
# Find nearby locations (radius search)
{:ok, nearby} = SoliDB.Geo.near(client, "stores",
latitude: 48.8566,
longitude: 2.3522,
radius: 5000, # meters
limit: 20 # optional
)
Enum.each(nearby, fn result ->
IO.puts("#{result["doc"]["name"]} - #{result["distance"]}m away")
end)
# Find within polygon
polygon = %{
type: "Polygon",
coordinates: [[[2.3, 48.8], [2.4, 48.8], [2.4, 48.9], [2.3, 48.9], [2.3, 48.8]]]
}
{:ok, within} = SoliDB.Geo.within(client, "stores", geometry: polygon)
# Find intersecting geometries
{:ok, intersects} = SoliDB.Geo.intersects(client, "zones", geometry: polygon)
# Calculate distance between two points
{:ok, distance} = SoliDB.Geo.distance(client,
lat1: 48.8566, lon1: 2.3522,
lat2: 51.5074, lon2: -0.1278
)
IO.puts("Paris to London: #{distance / 1000}km")
# List geo indexes
{:ok, indexes} = SoliDB.Geo.list_indexes(client, "stores")
# Delete index
:ok = SoliDB.Geo.delete_index(client, "stores", "location_idx")
SoliDB.TTL
Time-To-Live Indexesclient = SoliDB.Client.use_database(client, "mydb")
# Create TTL index (auto-expire documents)
:ok = SoliDB.TTL.create_index(client, "sessions",
name: "session_ttl",
field: "created_at", # DateTime field to check
expire_after_seconds: 3600 # Expire after 1 hour
)
# Update expiration time
:ok = SoliDB.TTL.update_expiration(client, "sessions", "session_ttl", 7200) # 2 hours
# Get index info
{:ok, info} = SoliDB.TTL.get_index_info(client, "sessions", "session_ttl")
IO.puts("Expires after: #{info["expire_after_seconds"]}s")
# Manually trigger cleanup (normally runs automatically)
{:ok, result} = SoliDB.TTL.run_cleanup(client, "sessions")
IO.puts("Deleted #{result["deleted"]} expired documents")
# List TTL indexes
{:ok, indexes} = SoliDB.TTL.list_indexes(client, "sessions")
# Delete TTL index
:ok = SoliDB.TTL.delete_index(client, "sessions", "session_ttl")
SoliDB.Columnar
Columnar/Analytics Storageclient = SoliDB.Client.use_database(client, "mydb")
# Create a columnar table (optimized for analytics)
{:ok, table} = SoliDB.Columnar.create(client, "metrics", [
%{name: "timestamp", type: "datetime"},
%{name: "metric_name", type: "string"},
%{name: "value", type: "float"},
%{name: "tags", type: "string"}
])
# Insert rows (batch insert is efficient)
:ok = SoliDB.Columnar.insert(client, "metrics", [
%{timestamp: "2024-01-15T10:00:00Z", metric_name: "cpu_usage", value: 45.2, tags: "server1"},
%{timestamp: "2024-01-15T10:01:00Z", metric_name: "cpu_usage", value: 47.8, tags: "server1"},
%{timestamp: "2024-01-15T10:00:00Z", metric_name: "memory", value: 72.1, tags: "server1"}
])
# Query with SQL-like syntax
{:ok, results} = SoliDB.Columnar.query(client, "metrics",
"SELECT * FROM metrics WHERE value > @min ORDER BY timestamp DESC LIMIT 100",
params: %{min: 40.0}
)
# Aggregation
{:ok, agg} = SoliDB.Columnar.aggregate(client, "metrics", %{
group_by: ["metric_name", "tags"],
metrics: [
%{column: "value", function: "avg"},
%{column: "value", function: "max"},
%{column: "value", function: "min"},
%{column: "value", function: "count"}
],
filters: %{metric_name: "cpu_usage"} # optional
})
# Get table statistics
{:ok, stats} = SoliDB.Columnar.stats(client, "metrics")
IO.puts("Row count: #{stats["row_count"]}, Size: #{stats["size_bytes"]}")
# Add a column
:ok = SoliDB.Columnar.add_column(client, "metrics",
column_name: "host",
column_type: "string",
default_value: "unknown" # optional
)
# Drop a column
:ok = SoliDB.Columnar.drop_column(client, "metrics", "host")
# Create index on columnar table
:ok = SoliDB.Columnar.create_index(client, "metrics",
index_name: "idx_timestamp",
column: "timestamp",
index_type: "btree" # optional
)
# List indexes
{:ok, indexes} = SoliDB.Columnar.list_indexes(client, "metrics")
# Delete index
:ok = SoliDB.Columnar.delete_index(client, "metrics", "idx_timestamp")
# List all columnar tables
{:ok, tables} = SoliDB.Columnar.list(client)
# Get table info
{:ok, table} = SoliDB.Columnar.get(client, "metrics")
# Delete table
:ok = SoliDB.Columnar.delete(client, "metrics")
SoliDB.Cluster
Cluster Management# Get cluster status
{:ok, status} = SoliDB.Cluster.status(client)
IO.puts("Mode: #{status["mode"]}") # standalone, cluster
IO.puts("Nodes: #{status["node_count"]}")
# Get detailed cluster info
{:ok, info} = SoliDB.Cluster.info(client)
# Get all nodes
{:ok, nodes} = SoliDB.Cluster.get_nodes(client)
Enum.each(nodes, fn node ->
IO.puts("#{node["id"]}: #{node["address"]} (#{node["status"]})")
end)
# Get shard distribution
{:ok, shards} = SoliDB.Cluster.get_shards(client)
# Remove a node from cluster
:ok = SoliDB.Cluster.remove_node(client, "node-id-to-remove")
# Trigger data rebalancing
:ok = SoliDB.Cluster.rebalance(client)
# Cleanup orphaned data
:ok = SoliDB.Cluster.cleanup(client)
# Reshard cluster
:ok = SoliDB.Cluster.reshard(client, 16) # new number of shards
SoliDB.CollectionsOps
Advanced Collection Operationsclient = SoliDB.Client.use_database(client, "mydb")
# Truncate collection (delete all documents)
:ok = SoliDB.CollectionsOps.truncate(client, "logs")
# Compact collection (reclaim disk space)
:ok = SoliDB.CollectionsOps.compact(client, "users")
# Repair collection (fix inconsistencies)
:ok = SoliDB.CollectionsOps.repair(client, "orders")
# Get collection statistics
{:ok, stats} = SoliDB.CollectionsOps.stats(client, "users")
# Prune old documents
:ok = SoliDB.CollectionsOps.prune(client, "logs",
older_than: "2024-01-01T00:00:00Z",
field: "created_at"
)
# Recount documents
:ok = SoliDB.CollectionsOps.recount(client, "users")
# Set JSON schema validation
:ok = SoliDB.CollectionsOps.set_schema(client, "users", %{
type: "object",
required: ["name", "email"],
properties: %{
name: %{type: "string", minLength: 1},
email: %{type: "string", format: "email"},
age: %{type: "integer", minimum: 0}
}
})
# Get current schema
{:ok, schema} = SoliDB.CollectionsOps.get_schema(client, "users")
# Remove schema validation
:ok = SoliDB.CollectionsOps.delete_schema(client, "users")
# Export collection
{:ok, data} = SoliDB.CollectionsOps.export(client, "users", "json") # json, csv, msgpack
# Import data
:ok = SoliDB.CollectionsOps.import(client, "users_backup", data, "json")
# Get sharding configuration
{:ok, sharding} = SoliDB.CollectionsOps.get_sharding(client, "orders")
# Configure sharding
:ok = SoliDB.CollectionsOps.set_sharding(client, "orders", %{
num_shards: 8,
shard_key: "user_id"
})
SoliDB.Env
Environment Variablesclient = SoliDB.Client.use_database(client, "mydb")
# List environment variables (for Lua scripts)
{:ok, vars} = SoliDB.Env.list(client)
# Set an environment variable
:ok = SoliDB.Env.set(client, "API_KEY", "sk-xxx-your-api-key")
:ok = SoliDB.Env.set(client, "WEBHOOK_URL", "https://example.com/webhook")
# Delete an environment variable
:ok = SoliDB.Env.delete(client, "OLD_VAR")
Error Handling
# All functions return {:ok, result} or {:error, reason}
case SoliDB.Client.connect("127.0.0.1", 6745) do
{:ok, client} ->
case SoliDB.Client.auth(client, "mydb", "user", "password") do
:ok ->
case SoliDB.Client.get(client, "mydb", "users", "nonexistent-key") do
{:ok, doc} ->
IO.inspect(doc)
{:error, %SoliDB.Error{type: :not_found}} ->
IO.puts("Document not found")
{:error, %SoliDB.Error{type: :permission_denied, message: msg}} ->
IO.puts("Access denied: #{msg}")
{:error, error} ->
IO.puts("Server error: #{inspect(error)}")
end
{:error, reason} ->
IO.puts("Authentication failed: #{inspect(reason)}")
end
SoliDB.Client.close(client)
{:error, %SoliDB.Error{type: :connection_refused}} ->
IO.puts("Cannot connect to server")
{:error, %SoliDB.Error{type: :timeout}} ->
IO.puts("Connection timeout")
end
Connection Errors
:connection_refused, :timeout, :closed - Network failures and disconnections
Server Errors
:not_found, :permission_denied, :validation_error - Server-side issues
Protocol Errors
:decode_error, :invalid_response - Serialization issues