Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/copilot-setup-steps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
- name: Setup Bun
uses: oven-sh/setup-bun@v2
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.8

Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/dockerize-profiles.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,20 @@ jobs:

steps:
- name: Checkout the repo
uses: actions/checkout@v2
uses: actions/checkout@0717577d45739eb3c851188b29f50ed6c0b2194e # v2.8.0
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@885d1462b80bc1c1c7f0b00334ad271f09369c55 # v2.10.0
- name: Log in to Docker Hub
uses: docker/login-action@v3
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
with:
images: appwrite/console-profiles
tags: |
Expand All @@ -40,7 +40,7 @@ jobs:

- name: Build and push Docker image
id: push
uses: docker/build-push-action@v6
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
with:
context: .
push: true
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ jobs:
e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- name: Setup Bun
uses: oven-sh/setup-bun@v2
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.8

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Cache Playwright browsers
uses: actions/cache@v4
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
id: playwright-cache
with:
path: ~/.cache/ms-playwright
Expand All @@ -34,7 +34,7 @@ jobs:

- name: E2E Tests
run: bun test:e2e
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
if: ${{ !cancelled() }}
with:
name: playwright-report
Expand Down
46 changes: 23 additions & 23 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
uses: actions/checkout@v2
uses: actions/checkout@0717577d45739eb3c851188b29f50ed6c0b2194e # v2.8.0
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@885d1462b80bc1c1c7f0b00334ad271f09369c55 # v2.10.0
- name: Log in to Docker Hub
uses: docker/login-action@v3
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
with:
images: appwrite/console-cloud
tags: |
Expand All @@ -30,7 +30,7 @@ jobs:
type=semver,pattern={{major}}
- name: Build and push Docker image
id: push
uses: docker/build-push-action@v6
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
with:
context: .
push: true
Expand All @@ -51,19 +51,19 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
uses: actions/checkout@v2
uses: actions/checkout@0717577d45739eb3c851188b29f50ed6c0b2194e # v2.8.0
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@885d1462b80bc1c1c7f0b00334ad271f09369c55 # v2.10.0
- name: Log in to Docker Hub
uses: docker/login-action@v3
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
with:
images: appwrite/console-cloud-stage
tags: |
Expand All @@ -72,7 +72,7 @@ jobs:
type=semver,pattern={{major}}
- name: Build and push Docker image
id: push
uses: docker/build-push-action@v6
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
with:
context: .
push: true
Expand All @@ -91,13 +91,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
uses: actions/checkout@v2
uses: actions/checkout@0717577d45739eb3c851188b29f50ed6c0b2194e # v2.8.0
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@885d1462b80bc1c1c7f0b00334ad271f09369c55 # v2.10.0
- name: Log in to Docker Hub
uses: docker/login-action@v3
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
Expand All @@ -112,7 +112,7 @@ jobs:
type=semver,pattern={{major}}
- name: Build and push Docker image
id: push
uses: docker/build-push-action@v6
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
with:
context: .
push: true
Expand All @@ -130,19 +130,19 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
uses: actions/checkout@v2
uses: actions/checkout@0717577d45739eb3c851188b29f50ed6c0b2194e # v2.8.0
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@885d1462b80bc1c1c7f0b00334ad271f09369c55 # v2.10.0
- name: Log in to Docker Hub
uses: docker/login-action@v3
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
with:
images: appwrite/console-cloud-no-regions
tags: |
Expand All @@ -151,7 +151,7 @@ jobs:
type=semver,pattern={{major}}
- name: Build and push Docker image
id: push
uses: docker/build-push-action@v6
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
with:
context: .
push: true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/stale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/stale@v9
- uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: "This issue has been labeled as a 'question', indicating that it requires additional information from the requestor. It has been inactive for 7 days. If no further activity occurs, this issue will be closed in 14 days."
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- name: Setup Bun
uses: oven-sh/setup-bun@v2
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.8

Expand Down
23 changes: 23 additions & 0 deletions src/lib/helpers/timeConversion.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
calculateTime,
formatReplicationLag,
timeToSeconds,
timeToMinutes,
secsToUnit
Expand Down Expand Up @@ -169,3 +170,25 @@ describe('Seconds to unit', () => {
});
});
});

describe('Format replication lag', () => {
it('renders an unknown lag as a dash', () => {
expect(formatReplicationLag(null)).toBe('-');
expect(formatReplicationLag(undefined)).toBe('-');
});

it('renders zero as a bound rather than an exact reading', () => {
// MySQL and MongoDB report whole seconds, so their 0 covers everything
// up to a second. Printing it as 0s claimed a precision no engine gives.
expect(formatReplicationLag(0)).toBe('< 1s');
});

it('renders a sub-second lag in milliseconds', () => {
expect(formatReplicationLag(0.184)).toBe('184ms');
});

it('renders a lag of a second or more in the largest fitting unit', () => {
expect(formatReplicationLag(7)).toBe('7s');
expect(formatReplicationLag(90)).toBe('1m');
});
});
21 changes: 21 additions & 0 deletions src/lib/helpers/timeConversion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,27 @@ export function calculateTime(time: number) {
}
}

/**
* Formats a replication lag reading for display.
*
* A zero renders as `< 1s` rather than `0s` because it does not mean the same
* thing on every engine: MySQL reports `Seconds_Behind_Source` in whole seconds
* and MongoDB derives its lag from the oplog timestamp's second granularity, so
* neither can distinguish "caught up" from "900ms behind". Only PostgreSQL
* reports a true zero, and the reading carries no engine to tell them apart.
*
* @export
* @param {number | null | undefined} lagSeconds - The lag in seconds, or null when the backend took no reading.
* @returns {string} The formatted lag, or `-` when the lag is unknown.
*/
export function formatReplicationLag(lagSeconds: number | null | undefined): string {
if (typeof lagSeconds !== 'number' || Number.isNaN(lagSeconds)) {
return '-';
}

return lagSeconds <= 0 ? '< 1s' : calculateTime(lagSeconds);
}

type Unit = 'ms' | 's' | 'm' | 'h' | 'd' | 'M' | 'y';

export function timeToSeconds(time: number, unit: Unit) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import type { Models } from '@appwrite.io/console';
import { Badge, Layout } from '@appwrite.io/pink-svelte';
import { toLocaleDateTime } from '$lib/helpers/date';
import { formatReplicationLag } from '$lib/helpers/timeConversion';

let {
database
Expand All @@ -35,7 +36,7 @@
primaryRegion: string;
standbyRegion: string;
standbyStatus: 'healthy' | 'degraded' | 'unhealthy' | 'provisioning';
lagSeconds: number;
lagSeconds: number | null;
lastSyncedAt: string;
};

Expand Down Expand Up @@ -209,7 +210,8 @@
&bull; Standby: {crossRegionStatus.standbyRegion}
</span>
<span class="text u-x-small">
Lag: {crossRegionStatus.lagSeconds}s &bull; Last synced: {toLocaleDateTime(
Lag: {formatReplicationLag(crossRegionStatus.lagSeconds)} &bull;
Last synced: {toLocaleDateTime(
crossRegionStatus.lastSyncedAt
)}
</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
import { CardGrid, Modal } from '$lib/components';
import { Dependencies } from '$lib/constants';
import { formatReplicationLag } from '$lib/helpers/timeConversion';
import { Button, Form, InputSwitch, InputNumber, InputSelect } from '$lib/elements/forms';
import { addNotification } from '$lib/stores/notifications';
import { sdk } from '$lib/stores/sdk';
Expand Down Expand Up @@ -196,7 +197,7 @@
type={getHealthType(replica.status)}
content={replica.status} />
<span class="text u-x-small">
Lag: {replica.lagSeconds}s
Lag: {formatReplicationLag(replica.lagSeconds)}
</span>
</Layout.Stack>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
import { CardGrid, Modal } from '$lib/components';
import { Dependencies } from '$lib/constants';
import { formatReplicationLag } from '$lib/helpers/timeConversion';
import { Button, Form, InputSelect, InputCheckbox } from '$lib/elements/forms';
import { addNotification } from '$lib/stores/notifications';
import { sdk } from '$lib/stores/sdk';
Expand Down Expand Up @@ -176,7 +177,9 @@
</Layout.Stack>
<span class="text u-x-small">
{replica.sourceRegion} &rarr; {replica.targetRegion}
&bull; Lag: {replica.lagSeconds}s &bull; {replica.hostname}
&bull; Lag: {formatReplicationLag(
replica.lagSeconds
)} &bull; {replica.hostname}
</span>
</Layout.Stack>
<Button
Expand Down
Loading