AshScylla.DataLayer (AshScylla v0.5.0)

Copy Markdown View Source

An Ash data layer for ScyllaDB using Exandra (Ecto adapter for Cassandra/ScyllaDB).

This data layer implements the Ash.DataLayer behaviour to allow Ash resources to be backed by ScyllaDB/Cassandra.

Configuration

Configure your resource to use this data layer:

defmodule MyApp.MyResource do
  use Ash.Resource,
    data_layer: AshScylla.DataLayer

  attributes do
    uuid_primary_key :id
    attribute :name, :string
  end

  relationships do
    # Define relationships as needed
  end
end

Features Supported

  • :create - Create records
  • :read - Read records with filtering
  • :update - Update records
  • :destroy - Delete records
  • :filter - Filter queries
  • :limit - Limit results
  • :select - Select specific fields
  • :multitenancy - Keyspace-based multitenancy
  • :upsert - Upsert records (INSERT IF NOT EXISTS with LWT)
  • :update_query - Bulk update via filtered queries
  • :destroy_query - Bulk delete via filtered queries
  • :keyset - Token-based keyset pagination (the default pagination mode)
  • :distinct - DISTINCT on partition key columns
  • {:aggregate, :count} - Per-partition COUNT aggregates
  • {:atomic, :update} - Atomic updates via LWT (IF clauses)
  • {:atomic, :upsert} - Atomic upserts via LWT
  • :boolean_filter - OR filter rewriting to IN where possible

Limitations

Since ScyllaDB/Cassandra is a wide-column store, not all SQL features are supported:

  • No JOINs (use denormalization or multiple queries)
  • Expression calculations are done in Elixir post-processing (not in-database)
  • DISTINCT only works on partition key columns
  • Limited aggregation support
  • Combination queries (UNION/INTERSECT) are not supported
  • No transactions across partitions (lightweight transactions only)
  • Locking is a no-op (use LWT for conditional operations)
  • No complex WHERE clauses on non-primary key columns without secondary indexes
  • Cross-partition aggregates require materialized views
  • CQL ORDER BY only works on clustering columns within a partition
  • OFFSET is not natively supported in ScyllaDB

Summary

Types

t()

@type t() :: %AshScylla.DataLayer{
  atomic: atom() | nil,
  context: map(),
  filters: list(),
  keyset: term(),
  limit: pos_integer() | nil,
  offset: pos_integer() | nil,
  repo: module() | nil,
  resource: Ash.Resource.t(),
  select: [atom()] | nil,
  sorts: list(),
  table: String.t() | nil,
  tenant: term(),
  upsert?: boolean(),
  upsert_fields: [atom()],
  upsert_identity: atom() | nil
}