feat(ql3): establish 3.0 incubation baseline

This commit is contained in:
whyour
2026-08-12 00:25:26 +08:00
parent 4bf92dcfeb
commit c699c32461
2817 changed files with 779642 additions and 653 deletions
@@ -0,0 +1,303 @@
const fs = require('node:fs');
const { DatabaseSync } = require('node:sqlite');
const {
createPluginPackageQuarantineEvent,
} = require('@qinglong/runtime-core/plugin-package-quarantine');
const {
activateInstall,
pluginPackageTaskReconciliationFixture,
} = require('../../../../test/contracts/pluginPackageTaskReconciliationRepositoryContract.cjs');
const {
LocalSqliteOperationAuthority,
} = require('../../dist/authority/operationAuthority');
const {
LocalSqlitePluginPackageInstallRepository,
} = require('../../dist/plugin-package/pluginPackageInstallRepository');
const {
LocalSqlitePluginPackageMaterializedRevisionRepository,
} = require('../../dist/plugin-package/pluginPackageMaterializedRevisionRepository');
const {
LocalSqlitePluginPackageQuarantineRepository,
} = require('../../dist/plugin-package/pluginPackageQuarantineRepository');
const {
LocalSqlitePluginPackageTaskReconciliationRepository,
} = require('../../dist/plugin-package/pluginPackageTaskReconciliationRepository');
const { auditLocalSqliteReadiness } = require('../../dist/readiness/readiness');
const { migrateLocalSqlitePath } = require('../../dist/migration/migration');
const DIGEST_D = 'd'.repeat(64);
const DIGEST_E = 'e'.repeat(64);
const CRASH_POINTS = Object.freeze({
after_task_disable: Object.freeze({
timing: 'afterRun',
sql: 'INSERT INTO "QingLong3TaskDefinitionRevisions"',
durable: false,
}),
after_quarantine_event: Object.freeze({
timing: 'afterRun',
sql: 'INSERT INTO "QingLong3PluginPackageQuarantineEvents"',
durable: false,
}),
after_withdrawal_receipt: Object.freeze({
timing: 'afterRun',
sql: 'INSERT INTO "QingLong3PluginPackageWithdrawalReceipts"',
durable: false,
}),
before_commit: Object.freeze({
timing: 'beforeExec',
sql: 'COMMIT',
durable: false,
}),
after_commit: Object.freeze({
timing: 'afterExec',
sql: 'COMMIT',
durable: true,
}),
});
function fixture(profile) {
return pluginPackageTaskReconciliationFixture(`quarantine-crash-${profile}`, {
profile,
});
}
function event(value) {
const record = value.install.active;
return createPluginPackageQuarantineEvent({
mutationId: `quarantine-crash-${value.profile}`,
revocationReceiptDigest: DIGEST_D,
impactDigest: DIGEST_E,
target: {
projectId: record.projectId,
packageName: record.packageName,
installationId: record.installationId,
lockDigest: record.lockDigest,
installState: record.state,
installVersion: record.version,
installRecordDigest: record.recordDigest,
activeLockDigest: record.activeLockDigest,
},
proposer: { type: 'user', id: 'owner-a' },
confirmer: { type: 'user', id: 'owner-b' },
authorizationMode: 'dual_control',
reasonCode: 'confirmed_key_compromise',
occurredAtMs: record.updatedAtMs + 1,
});
}
function client(databasePath) {
const database = new DatabaseSync(databasePath);
database.exec('PRAGMA foreign_keys = ON');
return database;
}
async function setupScenario({ databasePath, profile }) {
await migrateLocalSqlitePath({ databasePath, profile });
const value = fixture(profile);
const database = client(databasePath);
database
.prepare(
`INSERT INTO "QingLong3Projects"
(id, name, slug, status, version, created_at_ms, updated_at_ms)
VALUES (?, ?, ?, 'active', 1, 1, 1)`,
)
.run(value.projectId, value.projectId, value.projectId);
const authority = new LocalSqliteOperationAuthority(database);
try {
const install = new LocalSqlitePluginPackageInstallRepository(authority);
const materialized =
new LocalSqlitePluginPackageMaterializedRevisionRepository(
authority,
value.registry,
);
const reconciliation =
new LocalSqlitePluginPackageTaskReconciliationRepository(
authority,
value.registry,
);
await activateInstall(install, value);
await materialized.publish(value.revision);
await reconciliation.reconcile(value.revision, {
async findActiveResourceGeneration() {
return value.revision.generation;
},
});
} finally {
await authority.close();
}
}
function writeCrashMarker(markerPath, pointName) {
const descriptor = fs.openSync(markerPath, 'wx', 0o600);
try {
fs.writeSync(
descriptor,
JSON.stringify({
schema: 'qinglong/sqlite-plugin-package-quarantine-crash-marker@v1',
point: pointName,
pid: process.pid,
}),
);
fs.fsyncSync(descriptor);
} finally {
fs.closeSync(descriptor);
}
}
function crashClient(database, pointName, markerPath) {
const point = CRASH_POINTS[pointName];
if (!point) throw new Error(`unknown crash point ${pointName}`);
let triggered = false;
const crash = () => {
if (triggered) return;
triggered = true;
writeCrashMarker(markerPath, pointName);
process.kill(process.pid, 'SIGKILL');
throw new Error(`SIGKILL did not terminate ${pointName}`);
};
const matches = (timing, sql) =>
!triggered && point.timing === timing && sql.trim().includes(point.sql);
return new Proxy(database, {
get(target, property) {
if (property === 'exec') {
return (sql) => {
if (matches('beforeExec', sql)) crash();
const result = target.exec(sql);
if (matches('afterExec', sql)) crash();
return result;
};
}
if (property === 'prepare') {
return (sql) => {
const statement = target.prepare(sql);
return new Proxy(statement, {
get(statementTarget, statementProperty) {
const value = Reflect.get(
statementTarget,
statementProperty,
statementTarget,
);
if (statementProperty === 'run') {
return (...values) => {
const result = value.apply(statementTarget, values);
if (matches('afterRun', sql)) crash();
return result;
};
}
return typeof value === 'function'
? value.bind(statementTarget)
: value;
},
});
};
}
const value = Reflect.get(target, property, target);
return typeof value === 'function' ? value.bind(target) : value;
},
});
}
async function runCrashScenario({
databasePath,
markerPath,
pointName,
profile,
}) {
const database = client(databasePath);
const authority = new LocalSqliteOperationAuthority(
crashClient(database, pointName, markerPath),
);
const value = fixture(profile);
await new LocalSqlitePluginPackageQuarantineRepository(authority, {
registry: value.registry,
activeSourceLimit: profile === 'edge' ? 4 : 16,
}).quarantine(event(value), () => {});
throw new Error(`crash point ${pointName} was not reached`);
}
async function verifyScenario({ databasePath, pointName, profile }) {
const point = CRASH_POINTS[pointName];
const value = fixture(profile);
const quarantineEvent = event(value);
const database = client(databasePath);
const authority = new LocalSqliteOperationAuthority(database);
try {
const repository = new LocalSqlitePluginPackageQuarantineRepository(
authority,
{
registry: value.registry,
activeSourceLimit: profile === 'edge' ? 4 : 16,
},
);
const beforeRecovery = await repository.findByEventDigest(
quarantineEvent.eventDigest,
);
if (point.durable !== (beforeRecovery !== null)) {
throw new Error(`${profile}/${pointName} durability is inconsistent`);
}
const recovered = await repository.quarantine(quarantineEvent, () => {});
if (recovered.status !== (point.durable ? 'existing' : 'created')) {
throw new Error(`${profile}/${pointName} replay status is inconsistent`);
}
const taskFacts = database
.prepare(
`SELECT revision.enabled, head.current_revision AS "currentRevision"
FROM "QingLong3TaskDefinitions" AS head
JOIN "QingLong3TaskDefinitionRevisions" AS revision
ON revision.project_id = head.project_id
AND revision.task_id = head.task_id
AND revision.revision = head.current_revision
WHERE head.project_id = ?
ORDER BY head.task_id`,
)
.all(value.projectId);
if (
taskFacts.length !== 2 ||
taskFacts.some((fact) => fact.enabled !== 0 || fact.currentRevision !== 2)
) {
throw new Error(`${profile}/${pointName} Task withdrawal is incomplete`);
}
await auditLocalSqliteReadiness(database);
const integrity = database.prepare('PRAGMA integrity_check').get();
const foreignKey = database
.prepare('SELECT * FROM pragma_foreign_key_check LIMIT 1')
.get();
const journal = database.prepare('PRAGMA journal_mode').get();
return Object.freeze({
profile,
pointName,
crashBeforeCommit: !point.durable,
durableAfterCrash: point.durable,
integrityCheck: Object.values(integrity)[0],
foreignKeyCheck: foreignKey === undefined ? 'ok' : 'failed',
journalMode: journal.journal_mode,
});
} finally {
await authority.close();
}
}
module.exports = {
CRASH_POINTS,
setupScenario,
verifyScenario,
};
if (require.main === module) {
const [, , action, databasePath, markerPath, pointName, profile] =
process.argv;
if (action !== 'crash') {
throw new Error('fixture action must be crash');
}
runCrashScenario({
databasePath,
markerPath,
pointName,
profile,
}).catch((error) => {
process.stderr.write(`${error.stack ?? error}\n`);
process.exitCode = 1;
});
}