feat(ql3): version worker support tier admission

This commit is contained in:
whyour
2026-08-20 12:02:15 +08:00
parent 6e11258d45
commit 6265e31dce
28 changed files with 616 additions and 57 deletions
@@ -527,6 +527,8 @@ if (!migrationConnectionString || !runtimeConnectionString) {
const capabilities = canonicalRemoteWorkerCapabilities({
architecture: 'arm64',
executors: ['remote-worker'],
protocolVersion: '1.0.0',
supportTier: 'tier1',
labels: { region: 'cn-east' },
capacity: { memoryBytes: 536870912 },
});
@@ -1227,7 +1229,7 @@ if (!migrationConnectionString || !runtimeConnectionString) {
);
const sessionId = '018f0000-0000-7000-8000-000000000021';
const capabilitiesJson =
'{"architecture":"arm64","executors":["remote-worker"]}';
'{"architecture":"arm64","executors":["remote-worker"],"protocolVersion":"1.0.0","supportTier":"tier1"}';
const response = await workerRequest(
application.address,
`/api/v3/worker-ingress/workers/worker-http-a/sessions/${sessionId}/register`,
@@ -43,6 +43,7 @@ function revision() {
function worker() {
const capabilities = canonicalRemoteWorkerCapabilities({
architecture: 'arm64', executors: ['remote-worker'],
protocolVersion: '1.0.0', supportTier: 'tier1',
});
return {
workerId: 'edge-1', sessionId: SESSION, generation: 2,
@@ -36,6 +36,10 @@ const {
} = require('@qinglong/runtime-core/remote-worker-lease-control');
const SESSION_ID = '018f5c64-9b9d-7f1a-8c2d-1234567890ac';
const CAPABILITIES_JSON =
'{"architecture":"arm64","executors":["remote-worker"],"protocolVersion":"1.0.0","supportTier":"tier1"}';
const CAPABILITIES_HASH =
'b3d79017d91c477ffdf4a4dcc4ce9135ca053c921922ce0221920f905d8a2aa4';
function metadata(operation, workerId = 'edge-1') {
return {
@@ -80,9 +84,8 @@ function fixture(overrides = {}) {
generation: command.generation,
version: command.expectedVersion + 1,
status: 'online',
capabilitiesJson: '{}',
capabilitiesHash:
'44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a',
capabilitiesJson: CAPABILITIES_JSON,
capabilitiesHash: CAPABILITIES_HASH,
maxConcurrentRuns: 1,
availableSlots: command.availableSlots,
registeredAtMs: 1,
@@ -150,9 +153,8 @@ test('uses exact versioned register and transition contracts', async () => {
generation: 1,
version: 0,
status: 'online',
capabilitiesJson: '{}',
capabilitiesHash:
'44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a',
capabilitiesJson: CAPABILITIES_JSON,
capabilitiesHash: CAPABILITIES_HASH,
maxConcurrentRuns: 1,
availableSlots: 1,
registeredAtMs: 1,
@@ -188,7 +190,7 @@ test('uses exact versioned register and transition contracts', async () => {
await context.pipeline.prepare(metadata('register'))
).handle({
schema: WORKER_SESSION_REGISTER_SCHEMA,
capabilitiesJson: '{}',
capabilitiesJson: CAPABILITIES_JSON,
capabilitiesHash: baseRecord.capabilitiesHash,
maxConcurrentRuns: 1,
availableSlots: 1,
@@ -208,6 +210,31 @@ test('uses exact versioned register and transition contracts', async () => {
assert.equal(transition.body.status, 'draining');
});
test('rejects unversioned Worker capabilities before repository registration', async () => {
let registered = false;
const context = fixture({
workers: {
async register() { registered = true; throw new Error('must not register'); },
async heartbeatAuthenticated() { throw new Error('not used'); },
async transitionAuthenticated() { throw new Error('not used'); },
async findById() { return null; },
async listAvailable() { throw new Error('not used'); },
},
});
const prepared = await context.pipeline.prepare(metadata('register'));
await assert.rejects(prepared.handle({
schema: WORKER_SESSION_REGISTER_SCHEMA,
capabilitiesJson: '{}',
capabilitiesHash:
'44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a',
maxConcurrentRuns: 1,
availableSlots: 1,
leaseDurationMs: 30_000,
}), (error) =>
error.statusCode === 400 && error.code === 'invalid_worker_request');
assert.equal(registered, false);
});
test('binds the credential Worker to the path and rejects before body access', async () => {
const { pipeline, events } = fixture();
await assert.rejects(