test(quality): add concurrency and real browser gates
This commit is contained in:
@@ -19,6 +19,7 @@ export type HealthSnapshotErrorCode =
|
||||
export interface HealthSnapshotInstance {
|
||||
readonly id: string;
|
||||
readonly origin: string;
|
||||
readonly revision: number;
|
||||
}
|
||||
|
||||
export interface HealthEnvelope {
|
||||
@@ -157,7 +158,32 @@ function transportErrorCode(error: unknown): SnapshotErrorCode {
|
||||
return 'UPSTREAM_UNAVAILABLE';
|
||||
}
|
||||
|
||||
const healthUrl = (origin: string): string => `${origin.replace(/\/$/, '')}/api/health`;
|
||||
function isValidOwner(
|
||||
instanceId: string,
|
||||
owner: HealthSnapshotInstance | undefined,
|
||||
): owner is HealthSnapshotInstance {
|
||||
if (
|
||||
!owner ||
|
||||
owner.id !== instanceId ||
|
||||
!Number.isSafeInteger(owner.revision) ||
|
||||
owner.revision <= 0
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
const parsed = new URL(owner.origin);
|
||||
return (
|
||||
(parsed.protocol === 'http:' || parsed.protocol === 'https:') &&
|
||||
parsed.origin === owner.origin &&
|
||||
parsed.username === '' &&
|
||||
parsed.password === ''
|
||||
);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const healthUrl = (origin: string): string => `${origin}/api/health`;
|
||||
|
||||
export class StatusSnapshotService {
|
||||
readonly #db: Database.Database;
|
||||
@@ -188,7 +214,7 @@ export class StatusSnapshotService {
|
||||
|
||||
async refreshHealth(instanceId: string): Promise<HealthSnapshot> {
|
||||
const instance = await this.#instances.get(instanceId);
|
||||
if (!instance) throw new StatusSnapshotError('INSTANCE_NOT_FOUND');
|
||||
if (!isValidOwner(instanceId, instance)) throw new StatusSnapshotError('INSTANCE_NOT_FOUND');
|
||||
|
||||
const generation = ++this.#nextGeneration;
|
||||
this.#latestGeneration.set(instanceId, generation);
|
||||
@@ -201,6 +227,12 @@ export class StatusSnapshotService {
|
||||
} catch (error) {
|
||||
transportError = error;
|
||||
}
|
||||
let currentOwner: HealthSnapshotInstance | undefined;
|
||||
try {
|
||||
currentOwner = await this.#instances.get(instanceId);
|
||||
} catch {
|
||||
// Owner lookup failures fence persistence, but do not discard the computed probe result.
|
||||
}
|
||||
const completed = this.#now();
|
||||
const observedAt = completed.toISOString();
|
||||
const previous = this.#previous(instanceId);
|
||||
@@ -216,7 +248,13 @@ export class StatusSnapshotService {
|
||||
const { snapshot } = classified;
|
||||
|
||||
if (this.#latestGeneration.get(instanceId) === generation) {
|
||||
this.#persist(snapshot, classified.persisted);
|
||||
if (
|
||||
isValidOwner(instanceId, currentOwner) &&
|
||||
currentOwner.origin === instance.origin &&
|
||||
currentOwner.revision === instance.revision
|
||||
) {
|
||||
this.#persist(instance, snapshot, classified.persisted);
|
||||
}
|
||||
this.#latestGeneration.delete(instanceId);
|
||||
}
|
||||
return Object.freeze({ ...snapshot, payload: Object.freeze({ ...snapshot.payload }) });
|
||||
@@ -354,18 +392,23 @@ export class StatusSnapshotService {
|
||||
};
|
||||
}
|
||||
|
||||
#persist(snapshot: HealthSnapshot, persisted: PersistedHealthEnvelope): void {
|
||||
#persist(
|
||||
owner: HealthSnapshotInstance,
|
||||
snapshot: HealthSnapshot,
|
||||
persisted: PersistedHealthEnvelope,
|
||||
): void {
|
||||
this.#db
|
||||
.prepare(
|
||||
`INSERT INTO status_snapshots
|
||||
(id,instance_id,category,state,payload_json,observed_at,expires_at,created_at)
|
||||
SELECT ?,id,'health',?,?,?,?,? FROM instances WHERE id=?
|
||||
SELECT ?,id,'health',?,?,?,?,? FROM instances
|
||||
WHERE id=? AND base_url=? AND config_revision=?
|
||||
ON CONFLICT(instance_id,category) DO UPDATE SET
|
||||
state=excluded.state,
|
||||
payload_json=excluded.payload_json,
|
||||
observed_at=excluded.observed_at,
|
||||
expires_at=excluded.expires_at
|
||||
WHERE excluded.observed_at > status_snapshots.observed_at`,
|
||||
WHERE excluded.observed_at >= status_snapshots.observed_at`,
|
||||
)
|
||||
.run(
|
||||
this.#id(),
|
||||
@@ -375,6 +418,8 @@ export class StatusSnapshotService {
|
||||
snapshot.expiresAt,
|
||||
snapshot.observedAt,
|
||||
snapshot.instanceId,
|
||||
owner.origin,
|
||||
owner.revision,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user