All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased
Changed
- BREAKING: Renamed DSL section from
ash_scylla dotoscylla do— matches other Ash data layers' naming convention - BREAKING: Removed
allow_filteringDSL option —ALLOW FILTERINGis never appended to queries; filter on unindexed columns is rejected at query-plan time with actionable error - BREAKING: Removed
offset/3callback andoffsetfield from query struct — CQL does not support OFFSET; use keyset pagination viapaging_stateinstead - BREAKING: Default pagination mode changed from
:offsetto:token - BREAKING: Removed
AshScylla.Error.retry_delay/1— callers should implement their own retry policy usingretryable?/1 - Moved query struct from
AshScylla.DataLayerto newAshScylla.Querymodule — single ownership of query data - Created
AshScylla.DataLayer.SecondaryIndexstruct — replaces ad-hoc maps fromparse_secondary_index/1 - Added cursor encoding/decoding helpers to
AshScylla.DataLayer.Pagination:encode_cursor/1,decode_cursor/1,page_opts/2,extract_paging_state/1 - Consolidated
handle_scylla_result/1andhandle_query_result/1into singlehandle_result/1in DataLayer - Removed
ALLOW FILTERINGfrom all generated CQL including aggregate queries and system_schema queries - Removed
needs_allow_filtering?/2from QueryBuilder - Updated
AshScylla.DataLayer.QueryOptimizerto useAshScylla.Queryand removedallow_filteringoption - Updated all documentation, guides, and error messages to reference
scyllablock instead ofash_scylla
Added
AshScylla.Querymodule — owns the query struct, providesnew/1andnew/2AshScylla.DataLayer.SecondaryIndexmodule — struct withparse/1,default_name/2,effective_name/3AshScylla.DataLayer.Pagination.encode_cursor/1— base64url encoding of paging_stateAshScylla.DataLayer.Pagination.decode_cursor/1— base64url decoding of cursorAshScylla.DataLayer.Pagination.page_opts/2— build query options from paging_stateAshScylla.DataLayer.Pagination.extract_paging_state/1— extract paging_state from result- Security test suite (130 tests): filter validation, query builder injection prevention, pagination safety, error handling safety, DataLayer security, DSL security, migration security
0.13.1
Added
AshScylla.Extensioncallbacks — fullAsh.Extensionbehaviour implementation withinstall/5,reset/1,rollback/1, andtear_down/1callbacks, enablingmix ash.install,mix ash.reset,mix ash.rollback, andmix ash.tear_downsupport
0.13.0
Changed
- Credo checks updated to use new module names (Credo.Check.Refactor.*, Credo.Check.Warning.Dbg, etc.)
- Unit tests no longer require Docker/container runtime (lazy-loaded container support)
- Prepared statement cache now uses
{repo, cql, keyspace, opts}key instead ofphash2(cql)for safer cross-keyspace isolation mix ash_scylla.migratenow discovers and executes schema files frompriv/migrationsbefore resource migrationsmix ash_scylla.genrepurposed — now generates schema migration files from Ash DSL resource definitions (was resource template generator). Scans project forAshScylla.DataLayerresources and producespriv/migrations/files withCREATE TABLE/CREATE INDEXCQLmix ash_scylla.new_template— new name for the oldmix ash_scylla.genresource template generation (mix ash_scylla.new_template User name:string)- Added
AshScylla.DataLayer.QueryOptimizermodule with per-query consistency, timeout, paging hints, and speculative retry policy configuration - Added
AshScylla.DataLayer.Collectionmodule for LIST/SET/MAP encoding, CQL generation, and CONTAINS filters - Added
AshScylla.DataLayer.Compressionmodule for application-level compression (LZ4, Snappy, Deflate, Zstd) - Added
AshScylla.DataLayer.Udtmodule for User Defined Type encoding/decoding - Added
AshScylla.DataLayer.SchemaMigrationfor automatic schema diff and migration - Added
AshScylla.Releasemodule for production migration tasks without Mix installed - Added
AshScylla.MixHelpersfor shared resource/repo discovery across Mix tasks - Added
mix ash_scylla.gen.repotask for generating Repo modules - Added
AshScylla.Applicationmodule with:ash_scylla_repo_cacheETS table
Fixed
run_query/2:FilterValidatoris now skipped whenallow_filteringis enabled on the resource — previously the validator raised before the query builder could appendALLOW FILTERING, making the DSL option dead code- MaterializedView tests now match quoted identifier output
schema_migration.exformatting fixesoffset/3now raises with clear error instead of silently dropping- Fixed
AshScylla.Test.ContainerEngine.ensure_running/0being undefined when running integration tests (removed env guard oncontainer_engine.exloading) - Fixed duplicate function clauses and unused default args in
data_layer_pipeline_test.exs - Fixed dialyzer type warnings on
rows[0]access afterlength(rows)check inscylla_integration_test.exs - Fixed unused variable warning in
data_layer_crud_test.exs - Fixed dialyzer type mismatch in
edge_cases_test.exsforfilter_to_cql!(:bad)
Added
invalidate/4with repo/opts context for targeted cache invalidationcache_key/4helper for repo+keyspace-scoped statement cachingAshScylla.Schema— behaviour for schema migration modules inpriv/migrations. Schema files implementchange/0returning CQL statement listsAshScylla.SchemaLoader— discovers and loads schema migration files frompriv/migrationsmix ash_scylla.gen --dev— auto-generates schema migration from all AshScylla resources with timestamp-based namemix ash_scylla.gen AddUserTable— generates schema migration with a specific module namemix ash_scylla.gen --resource MyApp.User— generates schema for a specific resource onlymix ash_scylla.new_template— generates Ash resource templates (oldmix ash_scylla.genbehavior)mix ash_scylla.new_template --domain MyApp.Domain— auto-prefixes resource name with domain module (e.g.User→MyApp.Domain.User)mix ash_scylla.new_template --resource MyApp.Domain.User— uses a fully-qualified resource module name, overriding the positional namemix ash_scylla.migrate --schemas-only— runs only schema files frompriv/migrationswithout resource migrations- Multi-domain support —
project_domains/0andfind_all_resources/0now gracefully skip invalid/non-DSL domain modules instead of crashing, enabling umbrella apps with mixed domain configurations ResourceGenerator.render_create_table/3— generatesCREATE TABLE IF NOT EXISTSandCREATE INDEX IF NOT EXISTSCQL from attribute lists- Test coverage for
AshScylla.Schemabehaviour,AshScylla.SchemaLoader,ResourceGenerator.render_create_table/3,Mix.Tasks.AshScylla.Gen, andMix.Tasks.AshScylla.NewTemplate
[0.10.0]
- Comprehensive test suite (
data_layer_comprehensive_test.exs) covering 65+ test cases for gaps in existing coverage:run_query/2edge cases (empty results, multiple rows, select, distinct, keyset pagination, AND/OR filters, sort+limit, nil content)filter/3OR rewriting edge cases (triple OR, different columns, nested AND/OR, single filter)sort/3edge cases (empty list, multiple items, map format, tuple format)bulk_create/3scenarios (empty list, batch_size, return_records?, error handling, map opts)source/1edge cases (empty string table, @table attribute, caching)repo/1edge cases (@repo attribute, caching, resource without DSL)upsert/4delegation toupsert/3run_aggregate_query/3(multiple aggregates, COUNT(field), empty aggregates, WHERE clause)distinct/3(multiple PK columns, mixed PK/non-PK, empty list)calculate/3(multiple calculations, module without calculate/2)handle_scylla_result/1(all 6 error paths)sanitize_identifier/1(valid/invalid identifiers)maybe_rewrite_or_to_in/1(4-way OR, nested AND, single equality)- DataLayer struct defaults verification
- Exhaustive
can?/2feature testing (supported, unsupported, tuples, nil/string/integer)
Fixed
Mix.Tasks.AshScylla.Setup: FixedArgumentError: invalid switch types/modifiers: :atomby changingOptionParserswitch type from:atomto:stringwith runtime module resolutionMix.Tasks.AshScylla.Setup: Fixed hardcoded:storage_serviceapp reference — now dynamically detects the OTP app fromMix.Project.config()Mix.Tasks.AshScylla.Setup: Now runsmix compilebefore resolving the repo module, ensuring the module is available when passed as--repoMix.Tasks.AshScylla.Setup: Improved error message when no repo is found — now suggests runningmix ash_scylla.gen.repofirstrun_aggregate_query/3: Handle empty page content ([]andnil) gracefully by returning0instead of crashing withMatchErrorfetch_by_primary_key/3: Return structuredScyllaErrorfor empty results instead of crashing withMatchError- Updated README test structure documentation
- Updated error handling guide with record-not-found and aggregate empty result scenarios
0.6.0 - 2026-06-11
Changed
- BREAKING: Migrated from Exandra/Ecto.Repo pattern to direct Xandra connections.
AshScylla.Reponow wrapsAshScylla.Connection(a GenServer aroundXandra.start_link/1) instead of using Ecto.Repo. AshScylla.Connectionreplaces the Exandra/Ecto.Repo pattern for direct Xandra connection management.AshScylla.Migratornow usesAshScylla.Connectioninstead of Ecto SQL migrations.- Resource definitions now use
domain:instead ofrepo:(Ash Framework best practice). - Relaxed Ash dependency from
~> 3.28to~> 3.0for broader compatibility.
Added
AshScylla.Connection— direct Xandra connection wrapper withquery/4,query!/4,prepare/3,prepare!/3,stop/1.AshScylla.Migrator.run_on/2andrun_on!/2— execute CQL on an existing named connection.- Prepared statement caching via
AshScylla.PreparedStatementCache. - Telemetry integration via
AshScylla.Telemetry. - Token-based pagination via
AshScylla.DataLayer.Pagination. - Async partition-aware batch operations via
AshScylla.DataLayer.Batch.batch_insert_async/3.
Fixed
- All documentation and examples updated to reflect Xandra migration (no more Ecto.Repo, Ecto.Migration, or Exandra references in user-facing code).
- Mock repos in tests now return proper
Xandra.Pagestructs instead of plain maps.
0.5.0 - 2026-06-11
Added
@specannotations across all public and private API modules.dialyxirfor CI type checking.- Filter validation to prevent ALLOW FILTERING anti-pattern.
AshScylla.ResourceGenerator—mix ash_scylla.gentask for scaffolding resources.- Dev container support (.devcontainer).
Fixed
- Integration tests can now be run with
mix test test/scylla_integration_test.exs --only integration. - Removed unused
require Loggerfrom several modules. - Updated README feature/limitation tables for ScyllaDB accuracy.
0.4.0 - 2026-06-10
Changed
- BREAKING: Removed
:sortand:offsetfrom@supported_features— these are not natively supported by ScyllaDB and were causing silent failures.can?(:sort)andcan?(:offset)now returnfalse. - Added
data_layer_keyset_by_default?/0returningtrue— keyset pagination is now the default pagination mode. - Added runtime
Logger.warninginsort/3andoffset/3callbacks to alert callers about ScyllaDB limitations. - Relaxed Ash dependency from
~> 3.24to~> 3.0for broader compatibility. - Moved
AshScylla.RepoandAshScylla.Migrationout of the Core ExDoc group into "Repo Helpers" and "Schema Helpers" respectively. - Clarified
AshScylla.Migrationdocs — it generates raw CQL DDL strings, not Ecto SQL migrations. - Updated
IMPLEMENTATION_SUMMARY.mddependency table to remove incorrectreactorandtestcontainersentries, add missing dev deps.
Fixed
- Removed unused
require LoggerfromFilterValidator,Dsl,Telemetryandrequire XandrafromDataLayer. - Updated test assertions to match new
can?/2behavior and current version0.4.0.
0.3.0 - 2026-06-09
Added
- Per-action consistency configuration via
per_action_consistencyDSL option - Token-based pagination support via
AshScylla.DataLayer.Pagination - Prepared statement caching via
AshScylla.PreparedStatementCache(GenServer + ETS) - Telemetry integration via
AshScylla.Telemetrywith query/batch span events AshScylla.Error.ScyllaErrorstructured error types with suggestions- Retry logic with error-type-specific delays
AshScylla.Repohelper module withcreate_keyspace/1,drop_keyspace/1,recommended_pool_size/0AshScylla.Migrationhelpers for CQL generation from Ash resources- Materialized view support with CQL generation
- Async partition-aware batch operations via
batch_insert_async/4 - Testcontainer-based integration tests
0.2.0 - 2025-01-01
Added
- Secondary index support in DSL and migration helpers
- Materialized view DSL configuration
- Batch operations (BATCH INSERT/UPDATE/DELETE)
- Bulk create support via
Ash.bulk_create - TTL (Time To Live) support for INSERT statements
- Consistency level configuration per resource
- Comprehensive error handling with Xandra error categorization
- QueryBuilder with filter-to-CQL conversion
- Edge case test suite
0.1.0 - 2024-06-01
Added
- Initial release
- Ash.DataLayer behaviour implementation for ScyllaDB via Xandra
- CRUD operations (create, read, update, destroy)
- Filter, sort, limit, offset, select support
- Multitenancy via keyspace-based tenant isolation
- Basic CQL query generation from Ash queries