fix: 修复 develop 调度锁、运行恢复与 Alpine 缓存并发 (#3070)

* fix: repair develop scheduler locks and runtime recovery

* test: wait for child reaping after verified termination

* fix: abort cron mutations when scheduler deletion fails
This commit is contained in:
whyour
2026-09-13 13:44:44 +08:00
committed by GitHub
parent 041a437453
commit 4eb27427f8
12 changed files with 350 additions and 46 deletions
+49
View File
@@ -0,0 +1,49 @@
const test = require('node:test');
const assert = require('node:assert/strict');
const grpc = require('@grpc/grpc-js');
const load = require('../helpers/load-security-module.cjs');
for (const method of ['addCron', 'delCron']) {
test(`${method} invalidates an uncertain timed-out write without replaying it`, async () => {
let writes = 0;
let invalidations = 0;
const timeout = Object.assign(new Error('response deadline exceeded'), {
code: grpc.status.DEADLINE_EXCEEDED,
});
const fake = {
waitForReady: (_deadline, callback) => callback(),
[method]: (_request, _metadata, _options, callback) => {
// The server may have applied the write before the response was lost.
writes++;
callback(timeout);
},
};
const client = load('back/schedule/client.ts', {
'../protos/cron': {
CronClient: class {
constructor() {
return fake;
}
},
},
'../config': { grpcPort: 5500 },
'../config/grpcCerts': {
getGrpcCerts: () => ({
caCert: 'ca',
clientKey: 'key',
clientCert: 'cert',
}),
},
'@grpc/grpc-js': { ...grpc, credentials: { createSsl: () => ({}) } },
}).default;
client.readiness.invalidate = () => invalidations++;
await assert.rejects(client[method]([]), (error) => error === timeout);
assert.equal(
invalidations,
1,
'reconcile from the DB after an uncertain RPC result',
);
assert.equal(timeout.status, 503);
assert.equal(writes, 1, 'do not replay an uncertain mutation');
});
}