Skip to content

Make change tracking retention configurable, defaulting to 30 days - #1

Merged
adospace merged 2 commits into
mainfrom
feature/configurable-change-retention
Aug 26, 2026
Merged

Make change tracking retention configurable, defaulting to 30 days#1
adospace merged 2 commits into
mainfrom
feature/configurable-change-retention

Conversation

@adospace

@adospace adospace commented Aug 26, 2026

Copy link
Copy Markdown
Owner

adospace/CoreSync#19 is merged. The CoreSync submodule now points at the resulting main commit (a3a4734), same tree as the branch it was stacked on. This PR is ready to merge on its own.

Why

Change tracking retention was whatever CoreSync's default happened to be — seven days — with no way to see or change it from the admin UI. A client that stays offline longer than that window cannot resume an incremental sync and has to be reinitialized from a fresh snapshot, so the window has to cover how long a device is realistically expected to go without connectivity. Seven days does not: field crews routinely go a week without a signal, and every one of them comes back to a sync that can never succeed.

What changed

Retention is now a per-data-store setting

  • ChangeRetentionDays on SqlServerDataStore, defaulting to 30, with a migration that backfills existing SQL Server data stores. The column is nullable because it belongs to one branch of the TPH hierarchy while the property is not — without the backfill an existing data store would fail to materialize on a null read.
  • Passed to the SqlServerCT configuration builder. Setting it explicitly is also what makes provisioning reconcile the retention on a database that already has change tracking on, where it would otherwise be ignored entirely.
  • Exposed in the create wizard and the edit page, shown only for native change tracking, validated to 1–365 days on both client and server.

Saving actually applies it

Storing the value changes nothing on a database that already has change tracking enabled — EnableChangeTrackingAsync only runs when it is off. So saving now issues the ALTER DATABASE through the new ApplyChangeRetentionAsync and reports the retention read back from sys.change_tracking_databases. A value that was stored but could not be applied — most often a missing ALTER DATABASE permission — says so, instead of showing a green "updated successfully" over a database that never changed. That failure mode is precisely how this class of bug is created.

A failed session says why it failed

SyncSessionService.ErrorAsync wrote a DiagnosticItem but no SyncSessionTrace. The message reached the Diagnostics page, but nothing led there from the session detail view — which is where anyone investigating a failed session looks first, and where failures raised before the per-table trace loop showed a session that stopped for no stated reason. It now writes both.

Worth knowing before merging

  • The backfill sets every existing SQL Server data store to 30 days, not just the one that prompted this. Their retention will be reconciled on next provision. That is the intent — the seven-day default is the bug — but it is a behaviour change across every data store this instance serves.
  • Longer retention grows the change tracking side tables. 30 days is the agreed trade; the UI says so next to the field.
  • Migrations are applied by MigrationHostedService at startup, so no deployment step is needed.

Test plan

  • Edit a change-tracking data store, save a new retention, confirm the success message reports the value read back from the database
  • Save with an account lacking ALTER DATABASE, confirm the error surfaces rather than a success message
  • Confirm SELECT retention_period, retention_period_units_desc, is_auto_cleanup_on FROM sys.change_tracking_databases WHERE database_id = DB_ID() reflects the new value
  • Confirm the field is hidden for trigger-based tracking and for SQLite/PostgreSQL data stores
  • Confirm a failed sync session now shows its reason in the session detail Traces list

Retention was whatever CoreSync's default happened to be - seven days - with no
way to see or change it. A client that stays offline longer than that window
cannot resume an incremental sync and has to be reinitialized from a fresh
snapshot, so the window has to cover how long a device is realistically expected
to go without connectivity. Seven days does not.

- Add ChangeRetentionDays to SqlServerDataStore, defaulting to 30, with a
  migration that backfills existing SQL Server data stores. The column is
  nullable because it belongs to one branch of the TPH hierarchy while the
  property is not, so without the backfill an existing data store would fail to
  materialize on a null read.
- Pass it to the SqlServerCT configuration builder. Setting it explicitly is
  also what makes provisioning reconcile the retention on a database that
  already has change tracking on, where it would otherwise be ignored.
- Expose it in the create wizard and the edit page, shown only for native change
  tracking, validated to 1-365 days on both sides. Saving a new value now issues
  the ALTER DATABASE and reports the retention read back from the database, so a
  value that was stored but could not be applied says so instead of showing a
  green "updated successfully".

Also record the reason a sync session failed in the session's own traces. It
reached DiagnosticItems already, but nothing led there from the session detail
view - which is where anyone investigating a failed session looks first, and
where the failures raised before the per-table trace loop showed a session that
stopped for no stated reason.
CoreSync#19 is merged, so the submodule can reference main rather than the
feature branch it was stacked on. Same tree, so no behaviour change here.
@adospace
adospace merged commit c1be1f6 into main Aug 26, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant