AshScylla.DataLayer.Dsl (AshScylla v0.10.0)

Copy Markdown View Source

DSL extensions for configuring ScyllaDB-specific options on Ash resources.

Supports Ash Framework 3.0+ features including base_filter, identities, aggregates, calculations, preparations, changes, validations, pipelines, multitenancy, code_interface, and extended action options.

Usage

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

  ash_scylla do
    table "my_table"
    keyspace "my_keyspace"
    consistency :quorum
    ttl 3600
    lwt true

    base_filter [status: "active"]
    default_context %{tenant: "org_123"}
    description "My resource description"

    secondary_index :email
    secondary_index [:name, :age]
    secondary_index :status, name: "idx_user_status"

    materialized_view :users_by_email,
      primary_key: [:email, :id],
      include_columns: [:name, :age]

    pagination :token
    per_action_consistency read: :one, create: :quorum
  end

  attributes do
    uuid_primary_key :id
    uuid_v7_primary_key :vid
    integer_primary_key :seq_id
    create_timestamp :inserted_at
    update_timestamp :updated_at
    attribute :name, :string, public?: true, writable?: true
    attribute :email, :string, sensitive?: false
    attribute :status, :string
    attribute :age, :integer
  end

  identities do
    identity :unique_email, [:email]
  end

  aggregates do
    count :total_count
    count :active_count, filter: [status: "active"]
  end

  calculations do
    calculate :display_name, :string, expr(name)
  end

  preparations do
    prepare build(:load, [:email])
  end

  changes do
    change fn changeset, _context -> changeset end
  end

  validations do
    validate attribute_equals(:status, "active")
  end

  pipelines do
    pipe_through :read
  end

  multitenancy do
    strategy :attribute
    attribute :org_id
  end

  code_interface do
    define :create_user
    define_calculation :active_count
  end

  relationships do
    belongs_to :organization, MyApp.Organization
    has_one :profile, MyApp.Profile
    has_many :posts, MyApp.Post
    many_to_many :tags, MyApp.Tag
  end

  actions do
    create :create do
      accept [:name, :email, :status]
      argument :organization_id, :uuid
      change fn changeset, _context -> changeset end
      validate present([:name])
    end

    read :read do
      prepare build(:load, [:email])
      pagination offset?: true, max_page_size: 100
      metadata :total_count, :integer
      filter [status: "active"]
    end

    update :update do
      accept [:name, :status]
      change fn changeset, _context -> changeset end
      validate present([:name])
    end

    destroy :destroy do
      soft? true
      change fn changeset, _context -> changeset end
    end
  end
end

Options

  • :table - The table name in ScyllaDB (overrides default)
  • :keyspace - The keyspace to use (overrides repo default)
  • :consistency - The consistency level for reads/writes
  • :ttl - Default TTL for inserted records (in seconds)
  • :lwt - Enable Lightweight Transactions (LWT) for atomic upserts using INSERT ... IF NOT EXISTS (default: false)
  • :secondary_index - Define secondary indexes for non-primary key columns
  • :materialized_view - Define materialized views with different primary key structure
  • :pagination - Pagination mode: :offset (default) or :token for token-based pagination
  • :per_action_consistency - Per-action consistency overrides as a keyword list, e.g. [read: :one, create: :quorum]
  • :base_filter - A filter expression applied to all queries on this resource (Ash 3.0)
  • :default_context - Default context map merged into every query/changeset (Ash 3.0)
  • :description - Human-readable description of the resource (Ash 3.0)
  • :identity - Define unique identity constraints for upsert operations
  • :aggregate - Define aggregate queries (count, sum, avg, min, max)
  • :calculation - Define expression-based calculations
  • :preparation - Define query preparations
  • :change - Define changes applied to changesets
  • :validation - Define attribute validations
  • :pipeline - Define action pipelines via pipe_through
  • :multitenancy - Configure multitenancy strategy (:context or :attribute)
  • :code_interface - Define code interface functions
  • :relationship - Define relationships (belongs_to, has_one, has_many, many_to_many)
  • :action - Define actions with extended options (accept, argument, change, validate, prepare, pagination, metadata, filter, soft?)

Features

The data layer supports:

  • Upsert (:upsert) - Insert-or-update semantics with optional LWT
  • Atomic updates ({:atomic, :update}) - LWT-based conditional updates
  • Atomic upserts ({:atomic, :upsert}) - LWT-based insert-or-update
  • Bulk update/destroy - update_query and destroy_query for filtered operations
  • Distinct - On partition-key columns only
  • Aggregates - COUNT via :count aggregate
  • Expression calculations - In-memory post-processing
  • Boolean filter - With OR-to-IN rewriting
  • Base filter - Automatic filter applied to all queries (Ash 3.0)
  • Default context - Context merged into all queries (Ash 3.0)
  • Identities - Unique constraints for upsert operations (Ash 3.0)
  • Multitenancy - Context-based and attribute-based strategies (Ash 3.0)

Summary

Functions

Gets the action configurations defined for a resource.

Gets the aggregates defined for a resource.

Macro for configuring ScyllaDB options in Ash resources.

Gets the base_filter configured for a resource.

Gets the calculations defined for a resource.

Gets the changes defined for a resource.

Gets the configured consistency level for a resource.

Gets the default_context configured for a resource.

Gets the description configured for a resource.

Checks if a column has a secondary index defined.

Gets the identities defined for a resource.

Gets the configured keyspace for a resource.

Gets the materialized views defined for a resource.

Gets the multitenancy configuration for a resource.

Gets the pagination mode for a resource.

Gets the per-action consistency configuration for a resource.

Gets the pipelines defined for a resource.

Gets the preparations defined for a resource.

Gets the relationships defined for a resource.

Gets the configured repo for a resource.

Gets the code_interface configuration for a resource.

Gets the secondary indexes defined for a resource.

Gets the configured table name for a resource.

Gets the configured TTL for a resource.

Gets the validations defined for a resource.

Functions

action_configs(resource)

@spec action_configs(module()) :: [map()]

Gets the action configurations defined for a resource.

Returns a list of maps with keys:

  • :type - the action type (:create, :read, :update, :destroy)
  • :name - the action name (atom)
  • :options - action options (accept, argument, change, validate, etc.)

aggregates(resource)

@spec aggregates(module()) :: [map()]

Gets the aggregates defined for a resource.

Returns a list of maps with keys:

  • :type - the aggregate type (:count, :sum, :avg, :min, :max)
  • :name - the aggregate name (atom)
  • :field - the field to aggregate on (optional)
  • :options - additional options (filter, etc.)

ash_scylla(list)

(macro)
@spec ash_scylla(keyword()) :: Macro.t()

Macro for configuring ScyllaDB options in Ash resources.

Examples

ash_scylla do
  table "users"
  keyspace "my_keyspace"
  consistency :quorum
  ttl 3600

  base_filter [status: "active"]
  default_context %{tenant: "org_123"}
  description "User accounts"

  secondary_index :email
  secondary_index [:name, :age]

  materialized_view :users_by_email,
    primary_key: [:email, :id],
    include_columns: [:name, :age]

  pagination :token
  per_action_consistency read: :one, create: :quorum

  identity :unique_email, [:email]

  aggregate :count, :total_users
  aggregate :count, :active_users, filter: [status: "active"]

  calculation :display_name, :string, expr(name)

  preparation build(:load, [:email])

  change fn changeset, _context -> changeset end

  validation present([:name])

  pipeline :read

  multitenancy do
    strategy :attribute
    attribute :org_id
  end

  code_interface do
    define :create_user
    define_calculation :active_users
  end

  relationship :belongs_to, :organization, MyApp.Organization
  relationship :has_one, :profile, MyApp.Profile
  relationship :has_many, :posts, MyApp.Post
  relationship :many_to_many, :tags, MyApp.Tag

  action :create, :create_user do
    accept [:name, :email]
    argument :organization_id, :uuid
    change fn changeset, _context -> changeset end
    validate present([:name])
  end

  action :read, :list_users do
    pagination offset?: true, max_page_size: 100
    metadata :total_count, :integer
    filter [status: "active"]
  end

  action :update, :update_user do
    accept [:name, :status]
    change fn changeset, _context -> changeset end
  end

  action :destroy, :delete_user do
    soft? true
  end
end

base_filter(resource)

@spec base_filter(module()) :: term() | nil

Gets the base_filter configured for a resource.

The base_filter is a filter expression that is automatically applied to all queries on this resource (Ash 3.0 feature).

calculations(resource)

@spec calculations(module()) :: [map()]

Gets the calculations defined for a resource.

Returns a list of maps with keys:

  • :name - the calculation name (atom)
  • :type - the calculation type (atom)
  • :expression - the expression to evaluate
  • :options - additional options

changes(resource)

@spec changes(module()) :: [map()]

Gets the changes defined for a resource.

consistency(resource)

@spec consistency(module()) :: atom() | nil

Gets the configured consistency level for a resource.

default_context(resource)

@spec default_context(module()) :: map() | nil

Gets the default_context configured for a resource.

The default_context is a map that is merged into every query and changeset context for this resource (Ash 3.0 feature).

description(resource)

@spec description(module()) :: String.t() | nil

Gets the description configured for a resource.

has_secondary_index?(resource, column)

@spec has_secondary_index?(module(), atom()) :: boolean()

Checks if a column has a secondary index defined.

identities(resource)

@spec identities(module()) :: [map()]

Gets the identities defined for a resource.

Returns a list of maps with keys:

  • :name - the identity name (atom)
  • :columns - list of column names (atoms)
  • :options - additional options

keyspace(resource)

@spec keyspace(module()) :: String.t() | nil

Gets the configured keyspace for a resource.

lwt(resource)

@spec lwt(module()) :: boolean()

materialized_views(resource)

@spec materialized_views(module()) :: [map()]

Gets the materialized views defined for a resource.

Returns a list of maps with keys:

  • :name - the view name (atom)
  • :config - the view configuration keyword list

multitenancy(resource)

@spec multitenancy(module()) :: map() | nil

Gets the multitenancy configuration for a resource.

Returns a map with keys:

  • :strategy - :context or :attribute
  • :attribute - the attribute name for :attribute strategy (optional)

pagination(resource)

@spec pagination(module()) :: :offset | :token

Gets the pagination mode for a resource.

Returns :offset or :token.

per_action_consistency(resource)

@spec per_action_consistency(module()) :: map()

Gets the per-action consistency configuration for a resource.

Returns a map of action_name => consistency_level.

pipelines(resource)

@spec pipelines(module()) :: [map()]

Gets the pipelines defined for a resource.

preparations(resource)

@spec preparations(module()) :: [map()]

Gets the preparations defined for a resource.

relationships(resource)

@spec relationships(module()) :: [map()]

Gets the relationships defined for a resource.

Returns a list of maps with keys:

  • :type - :belongs_to, :has_one, :has_many, or :many_to_many
  • :name - the relationship name (atom)
  • :target - the target resource module
  • :options - additional options

repo(resource)

@spec repo(module()) :: module() | nil

Gets the configured repo for a resource.

scylla_code_interface(resource)

@spec scylla_code_interface(module()) :: map() | nil

Gets the code_interface configuration for a resource.

secondary_indexes(resource)

@spec secondary_indexes(module()) :: [map()]

Gets the secondary indexes defined for a resource.

Returns a list of maps with keys:

  • :columns - list of column names (atoms)
  • :name - optional custom index name
  • :options - additional options

table(resource)

@spec table(module()) :: String.t() | nil

Gets the configured table name for a resource.

ttl(resource)

@spec ttl(module()) :: pos_integer() | nil

Gets the configured TTL for a resource.

validations(resource)

@spec validations(module()) :: [map()]

Gets the validations defined for a resource.