717ae1031e
Zanzibar-style authorization graph engine (direct/chain/TTU/defeasible/ binary modes, condensed snapshots, value relations) with 39 rigor test campaigns. Includes fixes for snapshot binary writer/reader format mismatch (snapshot-of-snapshot corruption), possibility write-boundary validation, empty-graph snapshot serialization, relation lookup cache direction collision, config-redefinition cache invalidation, binary threshold semantics, defeasible compiled routing, and comparator reason whitelisting.
102 lines
2.9 KiB
JavaScript
102 lines
2.9 KiB
JavaScript
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import { ShardedSnapshot } from '../src/core/shards/ShardedSnapshot.js';
|
|
import { FileShardStorage } from '../src/core/shards/FileShardStorage.js';
|
|
|
|
function parseArgs(argv) {
|
|
const args = new Map();
|
|
for (let i = 2; i < argv.length; i++) {
|
|
const value = argv[i];
|
|
if (!value.startsWith('--')) continue;
|
|
const [key, inline] = value.slice(2).split('=');
|
|
if (inline !== undefined) {
|
|
args.set(key, inline);
|
|
continue;
|
|
}
|
|
const next = argv[i + 1];
|
|
if (next && !next.startsWith('--')) {
|
|
args.set(key, next);
|
|
i++;
|
|
} else {
|
|
args.set(key, true);
|
|
}
|
|
}
|
|
return args;
|
|
}
|
|
|
|
function makeRng(seed = 1337) {
|
|
let state = seed >>> 0;
|
|
return () => {
|
|
state = (state * 1664525 + 1013904223) >>> 0;
|
|
return state / 0xffffffff;
|
|
};
|
|
}
|
|
|
|
function buildRelationMap(relationIdToName) {
|
|
const map = new Map();
|
|
for (let i = 0; i < relationIdToName.length; i++) {
|
|
map.set(relationIdToName[i], i);
|
|
}
|
|
return map;
|
|
}
|
|
|
|
const args = parseArgs(process.argv);
|
|
const manifestPath = args.get('manifest') || 'tmp/shards-complex-1m-16384/manifest.json';
|
|
const queries = Number(args.get('queries') || 200);
|
|
const seed = Number(args.get('seed') || 1234);
|
|
const userPool = Number(args.get('user-pool') || 5000);
|
|
const docPool = Number(args.get('doc-pool') || 5000);
|
|
|
|
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
const storage = new FileShardStorage(path.dirname(manifestPath));
|
|
const snapshot = new ShardedSnapshot(manifest, storage, { cacheLimit: 32, recentLimit: 128 });
|
|
snapshot.initializeSync();
|
|
|
|
const relationIds = buildRelationMap(manifest.relationIdToName || []);
|
|
const rng = makeRng(seed);
|
|
|
|
const userIds = [];
|
|
for (let i = 0; i < userPool; i++) {
|
|
const id = snapshot.resolveNodeId(`user:${i}`);
|
|
if (id !== -1) userIds.push(id);
|
|
}
|
|
|
|
const docIds = [];
|
|
for (let i = 0; i < docPool; i++) {
|
|
const id = snapshot.resolveNodeId(`doc:${i}`);
|
|
if (id !== -1) docIds.push(id);
|
|
}
|
|
|
|
const memberRel = relationIds.get('member');
|
|
const viewerRel = relationIds.get('viewer');
|
|
|
|
const chainPairs = [];
|
|
for (let i = 0; i < queries; i++) {
|
|
const userId = userIds[Math.floor(rng() * userIds.length)];
|
|
const docId = docIds[Math.floor(rng() * docIds.length)];
|
|
chainPairs.push({ userId, docId });
|
|
}
|
|
|
|
console.log('Sharded plan/execute bench');
|
|
console.log(` manifest: ${manifestPath}`);
|
|
console.log(` queries: ${queries}`);
|
|
|
|
const plan = new Set();
|
|
for (const pair of chainPairs) {
|
|
snapshot.planOutEdges(memberRel, pair.userId, plan);
|
|
snapshot.planOutEdges(viewerRel, pair.userId, plan);
|
|
}
|
|
|
|
const planStart = process.hrtime.bigint();
|
|
snapshot.prefetchPlan(plan, (err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
process.exit(1);
|
|
}
|
|
const planTime = Number(process.hrtime.bigint() - planStart) / 1e6;
|
|
console.log(` prefetch time: ${planTime.toFixed(2)} ms`);
|
|
console.log(` plan size: ${plan.size}`);
|
|
console.log('Cache stats');
|
|
console.log(snapshot.getStats());
|
|
});
|