AshDyan.DataLayer behaviour (AshDyan v0.4.0)

Copy Markdown View Source

Behaviour describing what analysis capabilities a given Ash data layer supports.

AshDyan ships with implementations for AshPostgres and Ash.DataLayer.Simple (ETS). Other data layers fall back to a default that supports only the universally-safe capabilities (:frequency, :aggregate) and rejects :time_bucket/:percentile with a clear error rather than silently wrong results.

The capability check is surfaced explicitly via AshDyan.supports?/2 so callers can discover data-layer limits before issuing a query.

Extending with third-party data layers

The mapping from an Ash data-layer module to its AshDyan.DataLayer capability implementation is config-mergeable, so a downstream app can register its own data layer without patching AshDyan:

config :ash_dyan, :data_layer_capabilities, %{
  MyApp.CustomDataLayer => MyApp.AshDyan.CustomCapabilities
}

Or via an extension:

defmodule MyApp.AshDyan.Extension do
  @behaviour AshDyan.Extension

  def data_layer_capabilities do
    %{
      MyApp.CustomDataLayer => MyApp.AshDyan.CustomCapabilities
    }
  end
end

config :ash_dyan, :extensions, [MyApp.AshDyan.Extension]

Summary

Functions

Resolve the data-layer capability module for a resource.

Returns true if the resource's data layer supports the capability.

Callbacks

paginate(t, pos_integer, pos_integer)

(optional)
@callback paginate(Ash.Query.t(), pos_integer(), pos_integer()) ::
  {:ok, Ash.Query.t()} | {:error, term()}

pushdown_aggregate(t, atom, atom)

(optional)
@callback pushdown_aggregate(Ash.Query.t(), atom(), atom()) ::
  {:ok, Ash.Query.t()} | :not_supported

pushdown_time_bucket(t, atom, time_bucket)

(optional)
@callback pushdown_time_bucket(Ash.Query.t(), atom(), AshDyan.time_bucket()) ::
  {:ok, Ash.Query.t()} | :not_supported

Optional callback for SQL-pushdown of time bucketing.

A data layer that can express a time bucket natively (e.g. Postgres date_trunc) implements this and returns {:ok, query}. The default returns :not_supported, in which case the engine falls back to in-memory bucketing.

stream(t, keyword, keyword)

(optional)
@callback stream(Ash.Query.t(), keyword(), keyword()) ::
  {:ok, Enumerable.t()} | {:error, term()}

supports?(module, capability)

@callback supports?(module(), AshDyan.capability()) :: boolean()

Functions

for_resource(resource)

@spec for_resource(module()) :: module()

Resolve the data-layer capability module for a resource.

Built-in mappings are merged with config :ash_dyan, :data_layer_capabilities and extension configurations, so third-party data layers can register their own capability module.

supports?(resource, capability)

@spec supports?(module(), AshDyan.capability()) :: boolean()

Returns true if the resource's data layer supports the capability.