Skip to content

(fix): render a zero replication lag as a bound, not an exact reading - #3189

Closed
abnegate wants to merge 3 commits into
feat-dedicated-dbfrom
fix/dedicated-db-lag-display
Closed

abnegate wants to merge 3 commits into
feat-dedicated-dbfrom
fix/dedicated-db-lag-display

Conversation

@abnegate

@abnegate abnegate commented Aug 30, 2026

Copy link
Copy Markdown
Member

What

The three dedicated-database panels printed {lagSeconds}s raw, so a zero came out as 0s — a claim of exact currency that only PostgreSQL can actually make. The replication-lag column read 0s on every healthy replica of every engine.

New formatReplicationLag in $lib/helpers/timeConversion:

reading renders
null / undefined -
0 < 1s
0.184 184ms
7 7s
90 1m

Wired into updateHAStatus, updateReadReplicas and updateCrossRegion.

Why < 1s and not 0s

The reading carries no engine, and 0 does not mean the same thing on all three:

  • MySQL counts Seconds_Behind_Source in whole seconds.
  • MongoDB derives lag from optimeDate, which carries the oplog Timestamp's second granularity.
  • PostgreSQL is the only one that can report a true zero.

Measured on fra1 prod: db-6a674ee6001d5a176b00-0 prints Seconds_Behind_Source: 0 while streaming, and db-qafullmongo-0's optimeDate lands on .000Z. So on two engines out of three a 0 covers everything up to a second. < 1s is true on all three; 0s is wrong on two.

Passing the engine down so PostgreSQL could show a literal 0s was considered and dropped — it threads a field through three components to sharpen one edge case, and < 1s is not wrong for PostgreSQL either.

Sub-second readings render through the existing calculateTime, which already formats under-a-second as milliseconds. That is what the backend started publishing once it stopped rounding to whole seconds (appwrite-labs/edge#1281). Cross-region already published the raw float, so that panel was printing six decimals today.

CrossRegionStatus.lagSeconds is widened to number | null to match what the endpoint returns when no reading was taken.

Base branch

Targets feat-dedicated-db, not main — all three components exist only on that branch.

Verified

  • formatReplicationLag tests seen red against a broken formatter (0ms where < 1s was expected) and green with it.

  • vitest src/lib/helpers/timeConversion.test.ts: 94 pass.

  • prettier --check and eslint on all five changed files: clean.

  • svelte-check: zero new errors, measured by running it on origin/feat-dedicated-db and on this head with the same clean install and diffing. Both report 300 ERRORS 114 WARNINGS 167 FILES_WITH_PROBLEMS. The diff is five added and five removed, and they are the same five errors in updateReadReplicas.svelte shifted one line by the added import (32→33, 40→41, 54→55, 83→84, 118→119).

    Those 300 are pre-existing SDK-shape mismatches (Property 'listReadReplicas' does not exist on type 'Compute', Property 'create' does not exist on type 'Projects', and so on). @appwrite.io/console is installed from a branch URL rather than a version, so it moves under the lockfile — worth knowing before reading any type-error count on this branch as a signal.

Also: this PR has been merged up to date with feat-dedicated-db.

Not verified

  • No rendered screenshot. The panels were not exercised in a browser against a live dedicated database; the formatter is unit-tested and the call sites are a one-expression substitution.
  • This may not be the table you are looking at. A replication-lag table with an instance/role/status layout and a "Promote to primary" action does not exist anywhere in this repository, on any branch. If that component is uncommitted work, it needs the same substitution.
  • The two prettier reformats in updateHAStatus.svelte (the syncMode / initialSyncMode declarations) are unrelated to this change. They were already failing the repo's own prettier --check . before this branch.

🤖 Generated with Claude Code

The three dedicated-database panels printed `{lagSeconds}s` raw, so a zero
came out as `0s` -- a claim of exact currency that only PostgreSQL can
actually make. MySQL reports Seconds_Behind_Source in whole seconds and
MongoDB derives its lag from the oplog timestamp's second granularity, so
neither can tell "caught up" from "900ms behind", and the reading carries no
engine to tell them apart. `< 1s` is true on every engine.

Sub-second readings now render in milliseconds through calculateTime, which
is what the backend started publishing once it stopped rounding the reading
to whole seconds. Cross-region already published the raw float, so that panel
was printing six decimals.

CrossRegionStatus.lagSeconds is widened to number | null to match what the
endpoint returns when no reading was taken.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@appwrite

appwrite Bot commented Aug 30, 2026

Copy link
Copy Markdown

Console (appwrite/console)

Project ID: 688b7bf400350cbd60e9

Sites (1)
Site Status Logs Preview QR
 console-stage
688b7cf6003b1842c9dc
Failed Failed View Logs Preview URL QR Code

Tip

Silent mode disables those chatty PR comments if you prefer peace and quiet

@greptile-apps

greptile-apps Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR introduces a shared replication-lag formatter so unknown readings display as -, zero displays as < 1s, and positive values use human-readable units. It applies that formatter across the high-availability, read-replica, and cross-region panels, adds focused unit coverage, widens cross-region lag nullability, and pins workflow actions to immutable revisions.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
src/lib/helpers/timeConversion.ts Adds the shared replication-lag formatter with explicit handling for unknown and zero readings.
src/lib/helpers/timeConversion.test.ts Covers nullish, zero, sub-second, second, and minute replication-lag formatting.
src/routes/(console)/project-[region]-[project]/databases/database-[database]/settings/updateCrossRegion.svelte Uses the shared formatter and aligns the local lag type with nullable endpoint responses.
src/routes/(console)/project-[region]-[project]/databases/database-[database]/settings/updateHAStatus.svelte Replaces raw HA replica lag output with the shared formatter.
src/routes/(console)/project-[region]-[project]/databases/database-[database]/settings/updateReadReplicas.svelte Replaces raw read-replica lag output with the shared formatter.
.github/workflows/publish.yml Pins third-party workflow actions to immutable revisions corresponding to the documented versions.

Reviews (3): Last reviewed commit: "Merge remote-tracking branch 'origin/fea..." | Re-trigger Greptile

abnegate and others added 2 commits August 31, 2026 00:01
appwrite/console now refuses any action referenced by a moving tag: every job
in this repository dies at "Set up job" with "the actions ... are not allowed
in appwrite/console because all actions must be pinned to a full-length commit
SHA". It fails before checkout, so the whole repository's CI is down, not just
this branch -- the last green Tests/E2E run was 2026-08-26.

Every pin is the commit the moving tag resolves to today, so nothing changes
behaviourally; the version each SHA corresponds to is in a trailing comment.
publish.yml and dockerize-profiles.yml are covered too: they run on release
rather than on a pull request, so the policy would have surfaced there as a
failed publish instead of a failed check.

main carries a different set of workflow files (production.yml and staging.yml
exist there, and publish.yml differs), so it needs the same fix separately.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@abnegate

Copy link
Copy Markdown
Member Author

CI state: two repo-wide blockers, one fixed here, one not mine to fix

Neither is caused by this diff. The last green Tests / E2E run in this repository was 2026-08-26; these were the first PR runs since, and both blockers arrived in that window.

1. Action pinning — fixed in this PR

Every job died at Set up job:

The actions actions/checkout@v4, oven-sh/setup-bun@v2, actions/cache@v4, and actions/upload-artifact@v4 are not allowed in appwrite/console because all actions must be pinned to a full-length commit SHA.

That is before checkout, so no PR in this repository can run at all. 15fcc835 pins all 38 usages across the six workflow files to the commit each moving tag resolves to today — no behavioural change, version recorded in a trailing comment. It works: copilot-setup-steps went from failing to green, and build now gets past Set up job and through checkout.

main carries a different workflow set (production.yml and staging.yml exist there, publish.yml differs), so it needs the same fix separately.

2. bun audit --audit-level high — needs a dependency decision

build now fails one step later, on a pre-existing audit step that started failing because new advisories were published:

15 vulnerabilities (1 critical, 14 high)
  • critical vitest <3.2.6 (direct) — GHSA-5xrq-8626-4rwp
  • high @sveltejs/kit >=2.38.0 <=2.60.0 (direct) — adapter-node BODY_SIZE_LIMIT bypass, plus five moderates
  • high immutable <5.1.8 via sass
  • high devalue <=5.8.0 via @sveltejs/kit and svelte
  • high js-yaml <4.3.0 via eslint › @eslint/eslintrc
  • high ws <8.20.1 via jsdom

What I tried:

attempt result
Merge feat-dedicated-db in (this PR is now up to date with its base) still 15
bun update (compatible versions only) 15 → 12, clears the critical, still fails the gate

The remaining twelve need bun update --latest — major bumps of @sveltejs/kit, sass, eslint and postcss — or npm-style overrides pinning the transitive versions. Either is a dependency-posture decision for this repo, and I am not going to make a SvelteKit major bump inside a replication-lag display fix on a WIP branch, unverified. I reverted the bun update rather than leave a partial lockfile change that does not clear the gate.

So this PR cannot go green until the audit is resolved. The lag change itself is verified: vitest 94 pass (the new formatReplicationLag tests seen red first), prettier and eslint clean, svelte-check adds no new errors.

console-stage is a downstream Sites deployment and fails because build does.

@abnegate abnegate closed this Aug 30, 2026
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