Packages

An Elixir library for real-time state sync and delta tracking, with ETS, Redis, and periodic cleanup support.

Current section

Files

Jump to
chord CHANGELOG.md
Raw

CHANGELOG.md

# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/).
## [0.3.0] - 2026-03-07
### New Features
- **Telemetry instrumentation**: All public `Chord.Context.Manager` and `Chord.Cleanup` operations now emit `:telemetry` events, enabling monitoring and metrics integration.
- Context events: `[:chord, :context, :set|:get|:update|:delete|:sync, :start|:stop|:exception]`
- Cleanup events: `[:chord, :cleanup, :run, :start|:stop|:exception]`
- **CI/CD pipeline**: Added GitHub Actions workflow with matrix testing (Elixir 1.17/1.18, OTP 27), format checking, warnings-as-errors compilation, and Dialyzer static analysis.
- **Dialyzer support**: Added `dialyxir` for static type analysis with all issues resolved.
### Improvements
- **ETS backend rewrite**: Replaced composite key with `:ordered_set` table by simple key with `:set` table and atomic `ets.insert` upsert. Context lookups use O(1) `ets.lookup` instead of `match_object`. Added `:persistent_term` caching for table initialization. Benchmarks show 17-83% performance improvement across scenarios.
- **Optional dependencies**: `redix` and `jason` are now optional — only needed when using the Redis backend.
- **Redis SCAN**: Replaced `KEYS` command with cursor-based `SCAN` for production safety with large keyspaces.
- **Lazy Logger calls**: All Logger calls now use lazy evaluation to avoid unnecessary string allocations.
- **Cleanup crash resilience**: Cleanup server now wraps `periodic_cleanup` in try/rescue so the GenServer survives and reschedules even if a cleanup run raises.
- **Cleanup deduplication**: `cleanup_deltas_by_time` now deduplicates by `context_id` before calling the backend, avoiding redundant delete calls when multiple stale deltas exist for the same context.
- **Cleanup error handling**: All backend listing calls in cleanup (`list_contexts`, `list_deltas`, `list_contexts_with_delta_counts`) now gracefully handle `{:error, _}` responses instead of crashing.
### Fixed
- **Delta merge `old_value` preservation**: `merge_deltas/1` now correctly preserves the original `old_value` when merging chained modifications (e.g., added -> modified).
- **Delta merge falsiness bug**: `merge_deltas/1` no longer incorrectly discards `false` as an `old_value` due to `||` operator treating it as falsy.
- **Delta merge removed-then-added**: `merge_deltas/1` now correctly handles re-addition after removal (e.g., removed -> added produces `:modified` instead of silently dropping the re-add).
- **Empty delta list merge**: `merge_deltas([])` now returns `%{}` instead of crashing.
- **Nil value semantics**: Delta calculation now distinguishes between absent keys and keys with `nil` values using `is_map_key/2`.
- **Sync crash on empty deltas**: `sync_deltas_or_fallback` now pattern matches `{:ok, [_ | _]}` to prevent issues with empty delta lists.
- **ETS threshold inversion**: `delete_deltas_exceeding_threshold` now correctly keeps the newest versions instead of the oldest.
- **Context initialization error handling**: `get_or_initialize_context` now handles all error types, not just `:not_found`.
- **Delta formatter callback spec**: Fixed `Chord.Delta.Formatter.Behaviour` to accept both `map()` and `list(map())` return types.
- **Flaky async tests**: Cleanup tests now use `async: false` to prevent global `Application` env interference between test modules.
- **Mox verification**: All mock-based tests now use `Mox.verify_on_exit!` to ensure expectations are actually verified.
## [0.2.0] - 2025-01-27
### New Features
- Added time_unit configuration to allow users to define the time unit (:second or :millisecond) for generating timestamps.
### Improvements
- Delta calculation now handles nested structures more effectively. Example:
- Previous output:
```elixir
%{a: %{value: %{b: %{c: %{d: "d"}}}, action: :added}}
```
- New output:
```elixir
%{a: %{b: %{c: %{d: %{value: "d", action: :added}}}}}
```
This ensures a more logical representation of changes.
- The default delta formatter was redesigned to produce an output format that is easier to process, serialize, and consume. It now includes:
- Simplified structures.
- Improved usability for downstream consumers.
- Enhanced documentation across modules to improve usability and clarity.
- Other changes:
- Various minor adjustments and refinements for consistency and maintainability.
## [0.1.4] - 2025-01-22
### Added
- Enhanced `README.md` with detailed examples for using the Chord library.
- Unit tests for `calculate_delta` to handle `nil` values and ensure proper behavior when handling nested maps.
- Project logo
### Changed
- Updated `delta_ttl` configuration to use seconds for consistency across the library.
- Improved `calculate_delta` function to:
- Handle `nil` values appropriately.
- Mark changes as `:modified` when the old value is `nil`.
### Fixed
- Bug in Redis backend:
- `fetch_delta_counts/1` now correctly splits keys using `String.split/3` with `parts: 3` to handle keys with more than two colons.
## [0.1.3] - 2025-01-06
### Fixed
- Updated README.md to include missing details.
## [0.1.2] - 2025-01-06
### Fixed
- Fixed delta merging logic to correctly handle nested maps and ensure all changes are applied.
## [0.1.1] - 2025-01-05
### Fixed
- Corrected Redis configuration example in documentation.
- Fixed an issue in `Chord.Delta.calculate_delta/2` to correctly handle nested maps and avoid returning empty maps for unchanged nested structures.
## [0.1.0] - 2024-12-31
### Added
- Initial release of the Chord library.
- Real-time state synchronization with full and delta-based updates.
- Support for ETS and Redis backends.
- Developer-friendly APIs for setting, updating, and syncing contexts.
- Periodic cleanup of stale contexts and deltas.
- Support for context export and restore.
- Benchmark results showcasing performance for ETS and Redis under stateless and stateful architectures.