mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-05-15 22:30:38 +08:00
feat(authority): add server-primary capability probe
This commit is contained in:
142
tests/authority-browser-state.mjs
Normal file
142
tests/authority-browser-state.mjs
Normal file
@@ -0,0 +1,142 @@
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import {
|
||||
clearAuthorityOfflineQueue,
|
||||
enqueueAuthorityOfflineMutation,
|
||||
getAuthorityBrowserStateSnapshot,
|
||||
getAuthorityBrowserStoragePolicy,
|
||||
normalizeAuthorityBrowserState,
|
||||
recordAuthorityAcceptedRevision,
|
||||
} from "../sync/authority-browser-state.js";
|
||||
import { defaultSettings } from "../runtime/settings-defaults.js";
|
||||
|
||||
const policy = getAuthorityBrowserStoragePolicy(defaultSettings);
|
||||
assert.equal(policy.mode, "minimal");
|
||||
assert.equal(policy.offlineWritePolicy, "queue-local-dirty");
|
||||
assert.equal(policy.maxBytes, 1048576);
|
||||
assert.equal(policy.maxItems, 128);
|
||||
assert.equal(policy.maxAgeMs, 3600000);
|
||||
|
||||
const normalized = normalizeAuthorityBrowserState(
|
||||
{
|
||||
serverRevision: 7,
|
||||
serverIntegrity: "abc",
|
||||
offlineQueue: [
|
||||
{
|
||||
id: "old",
|
||||
createdAt: 0,
|
||||
bytes: 10,
|
||||
payload: { a: 1 },
|
||||
},
|
||||
{
|
||||
id: "fresh",
|
||||
createdAt: 9000,
|
||||
bytes: 20,
|
||||
payload: { b: 2 },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
...defaultSettings,
|
||||
authorityOfflineQueueMaxAgeMs: 1000,
|
||||
},
|
||||
10000,
|
||||
);
|
||||
assert.equal(normalized.serverRevision, 7);
|
||||
assert.equal(normalized.serverIntegrity, "abc");
|
||||
assert.equal(normalized.offlineQueueItems, 1);
|
||||
assert.equal(normalized.offlineQueueBytes, 20);
|
||||
assert.equal(normalized.offlineQueue[0].id, "fresh");
|
||||
|
||||
const acceptedRevision = recordAuthorityAcceptedRevision(
|
||||
normalized,
|
||||
{
|
||||
revision: 11,
|
||||
integrity: "server-integrity",
|
||||
},
|
||||
defaultSettings,
|
||||
12000,
|
||||
);
|
||||
assert.equal(acceptedRevision.serverRevision, 11);
|
||||
assert.equal(acceptedRevision.serverIntegrity, "server-integrity");
|
||||
assert.equal(acceptedRevision.lastCommitAt, 12000);
|
||||
assert.equal(acceptedRevision.offlineQueueItems, 1);
|
||||
|
||||
const enqueueResult = enqueueAuthorityOfflineMutation(
|
||||
acceptedRevision,
|
||||
{
|
||||
id: "mutation-1",
|
||||
kind: "commitDelta",
|
||||
payload: { upsertNodes: [{ id: "n1" }] },
|
||||
},
|
||||
{
|
||||
...defaultSettings,
|
||||
authorityOfflineQueueMaxItems: 3,
|
||||
},
|
||||
13000,
|
||||
);
|
||||
assert.equal(enqueueResult.accepted, true);
|
||||
assert.equal(enqueueResult.state.offlineQueueItems, 2);
|
||||
assert.equal(enqueueResult.state.offlineQueueOverflow, false);
|
||||
|
||||
const itemOverflow = enqueueAuthorityOfflineMutation(
|
||||
enqueueResult.state,
|
||||
{
|
||||
id: "mutation-overflow",
|
||||
payload: { upsertNodes: [{ id: "n2" }] },
|
||||
},
|
||||
{
|
||||
...defaultSettings,
|
||||
authorityOfflineQueueMaxItems: 1,
|
||||
},
|
||||
14000,
|
||||
);
|
||||
assert.equal(itemOverflow.accepted, false);
|
||||
assert.equal(itemOverflow.reason, "max-items-exceeded");
|
||||
assert.equal(itemOverflow.state.offlineQueueItems, 2);
|
||||
assert.equal(itemOverflow.state.offlineQueueOverflow, true);
|
||||
|
||||
const byteOverflow = enqueueAuthorityOfflineMutation(
|
||||
{},
|
||||
{
|
||||
id: "large-mutation",
|
||||
payload: { text: "x".repeat(64) },
|
||||
},
|
||||
{
|
||||
...defaultSettings,
|
||||
authorityOfflineQueueMaxBytes: 8,
|
||||
},
|
||||
15000,
|
||||
);
|
||||
assert.equal(byteOverflow.accepted, false);
|
||||
assert.equal(byteOverflow.reason, "max-bytes-exceeded");
|
||||
assert.equal(byteOverflow.state.offlineQueueItems, 0);
|
||||
assert.equal(byteOverflow.state.offlineQueueOverflow, true);
|
||||
|
||||
const disabled = enqueueAuthorityOfflineMutation(
|
||||
{},
|
||||
{
|
||||
id: "disabled-mutation",
|
||||
payload: { a: 1 },
|
||||
},
|
||||
{
|
||||
...defaultSettings,
|
||||
authorityBrowserCacheMode: "off",
|
||||
},
|
||||
16000,
|
||||
);
|
||||
assert.equal(disabled.accepted, false);
|
||||
assert.equal(disabled.reason, "offline-queue-disabled");
|
||||
|
||||
const cleared = clearAuthorityOfflineQueue(enqueueResult.state, defaultSettings, 17000);
|
||||
assert.equal(cleared.offlineQueueItems, 0);
|
||||
assert.equal(cleared.offlineQueueBytes, 0);
|
||||
assert.equal(cleared.offlineQueueOverflow, false);
|
||||
|
||||
const snapshot = getAuthorityBrowserStateSnapshot(acceptedRevision, defaultSettings, 18000);
|
||||
assert.equal(snapshot.serverRevision, 11);
|
||||
assert.equal(snapshot.serverIntegrity, "server-integrity");
|
||||
assert.equal(snapshot.offlineQueueItems, 1);
|
||||
assert.equal("offlineQueue" in snapshot, false);
|
||||
|
||||
console.log("authority-browser-state tests passed");
|
||||
116
tests/authority-capabilities.mjs
Normal file
116
tests/authority-capabilities.mjs
Normal file
@@ -0,0 +1,116 @@
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import {
|
||||
buildAuthorityProbeUrls,
|
||||
collectAuthorityFeatures,
|
||||
normalizeAuthorityCapabilityState,
|
||||
normalizeAuthoritySettings,
|
||||
probeAuthorityCapabilities,
|
||||
} from "../runtime/authority-capabilities.js";
|
||||
import { defaultSettings } from "../runtime/settings-defaults.js";
|
||||
|
||||
const normalizedSettings = normalizeAuthoritySettings(defaultSettings);
|
||||
assert.equal(normalizedSettings.enabled, true);
|
||||
assert.equal(normalizedSettings.enabledMode, "auto");
|
||||
assert.equal(normalizedSettings.baseUrl, "/api/plugins/authority");
|
||||
assert.equal(normalizedSettings.storageMode, "auto-server-primary");
|
||||
assert.equal(normalizedSettings.vectorMode, "auto-primary");
|
||||
assert.equal(normalizedSettings.primaryWhenAvailable, true);
|
||||
|
||||
assert.deepEqual(buildAuthorityProbeUrls("/api/plugins/authority/"), [
|
||||
"/api/plugins/authority/v1/diagnostics/probe",
|
||||
"/api/plugins/authority/v1/probe",
|
||||
"/api/plugins/authority/probe",
|
||||
"/api/plugins/authority",
|
||||
]);
|
||||
|
||||
const collected = collectAuthorityFeatures({
|
||||
features: ["sql.query", "trivium.search"],
|
||||
services: {
|
||||
sql: true,
|
||||
jobs: true,
|
||||
blob: true,
|
||||
},
|
||||
});
|
||||
assert.equal(collected.has("sql.query"), true);
|
||||
assert.equal(collected.has("trivium.search"), true);
|
||||
assert.equal(collected.has("sql"), true);
|
||||
assert.equal(collected.has("jobs"), true);
|
||||
assert.equal(collected.has("blob"), true);
|
||||
|
||||
const readyState = normalizeAuthorityCapabilityState(
|
||||
{
|
||||
installed: true,
|
||||
healthy: true,
|
||||
features: ["sql", "trivium", "jobs", "blob"],
|
||||
},
|
||||
defaultSettings,
|
||||
);
|
||||
assert.equal(readyState.serverPrimaryReady, true);
|
||||
assert.equal(readyState.storagePrimaryReady, true);
|
||||
assert.equal(readyState.triviumPrimaryReady, true);
|
||||
assert.equal(readyState.minimumFeatureSetReady, true);
|
||||
|
||||
const missingState = normalizeAuthorityCapabilityState(
|
||||
{
|
||||
installed: true,
|
||||
healthy: true,
|
||||
features: ["sql"],
|
||||
},
|
||||
defaultSettings,
|
||||
);
|
||||
assert.equal(missingState.serverPrimaryReady, false);
|
||||
assert.equal(missingState.triviumPrimaryReady, false);
|
||||
assert.ok(missingState.missingFeatures.includes("trivium.search"));
|
||||
|
||||
const disabledState = await probeAuthorityCapabilities({
|
||||
settings: {
|
||||
...defaultSettings,
|
||||
authorityEnabled: "off",
|
||||
},
|
||||
fetchImpl: async () => {
|
||||
throw new Error("should-not-fetch");
|
||||
},
|
||||
nowMs: 1000,
|
||||
});
|
||||
assert.equal(disabledState.reason, "disabled");
|
||||
assert.equal(disabledState.serverPrimaryReady, false);
|
||||
assert.equal(disabledState.lastProbeAt, 1000);
|
||||
|
||||
let requestedUrl = "";
|
||||
const probedState = await probeAuthorityCapabilities({
|
||||
settings: defaultSettings,
|
||||
allowRelativeUrl: true,
|
||||
nowMs: 2000,
|
||||
fetchImpl: async (url) => {
|
||||
requestedUrl = url;
|
||||
return {
|
||||
ok: true,
|
||||
status: 200,
|
||||
async json() {
|
||||
return {
|
||||
healthy: true,
|
||||
sessionReady: true,
|
||||
permissionReady: true,
|
||||
features: ["sql", "trivium", "jobs", "blob"],
|
||||
};
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
assert.equal(requestedUrl, "/api/plugins/authority/v1/diagnostics/probe");
|
||||
assert.equal(probedState.installed, true);
|
||||
assert.equal(probedState.healthy, true);
|
||||
assert.equal(probedState.serverPrimaryReady, true);
|
||||
assert.equal(probedState.lastProbeAt, 2000);
|
||||
|
||||
const relativeUnavailable = await probeAuthorityCapabilities({
|
||||
settings: defaultSettings,
|
||||
allowRelativeUrl: false,
|
||||
fetchImpl: async () => ({ ok: true, status: 200, json: async () => ({}) }),
|
||||
nowMs: 3000,
|
||||
});
|
||||
assert.equal(relativeUnavailable.reason, "relative-url-unavailable");
|
||||
assert.equal(relativeUnavailable.serverPrimaryReady, false);
|
||||
|
||||
console.log("authority-capabilities tests passed");
|
||||
@@ -68,6 +68,25 @@ assert.equal(defaultSettings.worldInfoFilterMode, "default");
|
||||
assert.equal(defaultSettings.worldInfoFilterCustomKeywords, "");
|
||||
assert.equal("maintenanceAutoMinNewNodes" in defaultSettings, false);
|
||||
assert.equal(defaultSettings.embeddingTransportMode, "direct");
|
||||
assert.equal(defaultSettings.authorityEnabled, "auto");
|
||||
assert.equal(defaultSettings.authorityBaseUrl, "/api/plugins/authority");
|
||||
assert.equal(defaultSettings.authorityPrimaryWhenAvailable, true);
|
||||
assert.equal(defaultSettings.authorityStorageMode, "auto-server-primary");
|
||||
assert.equal(defaultSettings.authorityVectorMode, "auto-primary");
|
||||
assert.equal(defaultSettings.authoritySqlPrimary, true);
|
||||
assert.equal(defaultSettings.authorityTriviumPrimary, true);
|
||||
assert.equal(defaultSettings.authorityGraphQueryEnabled, true);
|
||||
assert.equal(defaultSettings.authorityJobsEnabled, true);
|
||||
assert.equal(defaultSettings.authorityBlobCheckpointEnabled, true);
|
||||
assert.equal(defaultSettings.authorityBrowserCacheMode, "minimal");
|
||||
assert.equal(defaultSettings.authorityOfflineWritePolicy, "queue-local-dirty");
|
||||
assert.equal(defaultSettings.authorityOfflineQueueMaxBytes, 1048576);
|
||||
assert.equal(defaultSettings.authorityOfflineQueueMaxItems, 128);
|
||||
assert.equal(defaultSettings.authorityOfflineQueueMaxAgeMs, 3600000);
|
||||
assert.equal(defaultSettings.authorityVectorSyncChunkSize, 1000);
|
||||
assert.equal(defaultSettings.authorityVectorFailOpen, true);
|
||||
assert.equal(defaultSettings.authorityDiagnosticsEnabled, true);
|
||||
assert.equal(defaultSettings.authorityProbeIntervalMs, 60000);
|
||||
assert.equal(defaultSettings.graphUseNativeLayout, true);
|
||||
assert.equal(defaultSettings.graphNativeLayoutThresholdNodes, 280);
|
||||
assert.equal(defaultSettings.graphNativeLayoutThresholdEdges, 1600);
|
||||
|
||||
Reference in New Issue
Block a user