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,116 @@
import {
BoundedTaskListProjectionUnavailableError,
InvalidBoundedTaskListProjectionError,
executeBoundedTaskListProjection,
} from '@qinglong/runtime-core/bounded-task-list-projection';
import type { TaskDefinitionSource } from '@qinglong/runtime-core/task-definition';
import type { ClusterControlAdmissionResponse } from '../transport/httpSurface';
import type {
ClusterControlAuthorizedOperationRequest,
ClusterControlRouteDefinition,
} from '../transport/routeRegistry';
export const CLUSTER_CONTROL_TASK_LIST_ROUTE = Object.freeze({
method: 'GET' as const,
path: '/api/v3/projects/{projectId}/tasks',
operationId: 'task.list',
permission: 'task.read',
projectParameter: 'projectId',
allowedQuery: Object.freeze(['after_task_id', 'limit']),
});
const TASK_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
function response(
statusCode: number,
body: Readonly<Record<string, unknown>>,
): ClusterControlAdmissionResponse {
return Object.freeze({ statusCode, body: Object.freeze(body) });
}
function parseQuery(
query: Readonly<Record<string, readonly string[]>>,
): Readonly<{
limit?: number;
after?: Readonly<{ taskId: string }>;
}> {
const limitValues = query.limit;
const taskIdValues = query.after_task_id;
if (
(limitValues !== undefined && limitValues.length !== 1) ||
(taskIdValues !== undefined && taskIdValues.length !== 1)
) {
throw new TypeError();
}
const rawLimit = limitValues?.[0];
const limit = rawLimit === undefined ? undefined : Number(rawLimit);
const taskId = taskIdValues?.[0];
if (
(rawLimit !== undefined &&
(!Number.isSafeInteger(limit) ||
Number(limit) < 1 ||
Number(limit) > 64 ||
String(limit) !== rawLimit)) ||
(taskId !== undefined && !TASK_ID_PATTERN.test(taskId))
) {
throw new TypeError();
}
return Object.freeze({
...(limit === undefined ? {} : { limit }),
...(taskId === undefined
? {}
: { after: Object.freeze({ taskId }) }),
});
}
function validateTaskListQuery(
query: Readonly<Record<string, readonly string[]>>,
): void {
parseQuery(query);
}
export function createClusterControlTaskListRoute(
tasks: Pick<TaskDefinitionSource, 'listTaskDefinitions'>,
): Readonly<ClusterControlRouteDefinition> {
if (!tasks || typeof tasks.listTaskDefinitions !== 'function') {
throw new TypeError('Cluster-control Task list repository is invalid');
}
return Object.freeze({
...CLUSTER_CONTROL_TASK_LIST_ROUTE,
validateQuery: validateTaskListQuery,
async handle(authorized: ClusterControlAuthorizedOperationRequest) {
if (authorized.request.body !== null) {
return response(400, { code: 'invalid_request_body' });
}
if (authorized.projectId === null) {
return response(503, { code: 'task_list_unavailable' });
}
let input;
try {
input = parseQuery(authorized.request.query);
} catch {
return response(400, { code: 'invalid_task_list_query' });
}
try {
const result = await executeBoundedTaskListProjection(
tasks,
authorized.projectId,
input,
);
return response(200, { ...result });
} catch (error) {
if (
error instanceof InvalidBoundedTaskListProjectionError ||
error instanceof BoundedTaskListProjectionUnavailableError
) {
return response(503, { code: 'task_list_unavailable' });
}
throw error;
}
},
});
}
export * from './taskReadRoute';
export * from './taskStartRoute';
@@ -0,0 +1,70 @@
import {
BoundedTaskReadProjectionUnavailableError,
InvalidBoundedTaskReadProjectionError,
executeBoundedTaskReadProjection,
} from '@qinglong/runtime-core/bounded-task-read-projection';
import type { TaskDefinitionSource } from '@qinglong/runtime-core/task-definition';
import type { ClusterControlAdmissionResponse } from '../transport/httpSurface';
import type {
ClusterControlAuthorizedOperationRequest,
ClusterControlRouteDefinition,
ClusterControlRouteParameters,
} from '../transport/routeRegistry';
export const CLUSTER_CONTROL_TASK_READ_ROUTE = Object.freeze({
method: 'GET' as const,
path: '/api/v3/projects/{projectId}/tasks/{taskId}',
operationId: 'task.get',
permission: 'task.read',
projectParameter: 'projectId',
});
function response(
statusCode: number,
body: Readonly<Record<string, unknown>>,
): ClusterControlAdmissionResponse {
return Object.freeze({ statusCode, body: Object.freeze(body) });
}
export function createClusterControlTaskReadRoute(
tasks: Pick<TaskDefinitionSource, 'findCurrentTaskDefinition'>,
): Readonly<ClusterControlRouteDefinition> {
if (!tasks || typeof tasks.findCurrentTaskDefinition !== 'function') {
throw new TypeError('Cluster-control Task read repository is invalid');
}
return Object.freeze({
...CLUSTER_CONTROL_TASK_READ_ROUTE,
async handle(
authorized: ClusterControlAuthorizedOperationRequest,
parameters: ClusterControlRouteParameters,
) {
if (authorized.request.body !== null) {
return response(400, { code: 'invalid_request_body' });
}
if (authorized.projectId === null) {
return response(503, { code: 'task_query_unavailable' });
}
try {
const projection = await executeBoundedTaskReadProjection(
tasks,
authorized.projectId,
parameters.taskId!,
);
if (projection.found !== true) {
return response(404, { code: 'task_not_found' });
}
const { found: _found, ...task } = projection;
return response(200, { task: Object.freeze(task) });
} catch (error) {
if (
error instanceof InvalidBoundedTaskReadProjectionError ||
error instanceof BoundedTaskReadProjectionUnavailableError
) {
return response(503, { code: 'task_query_unavailable' });
}
throw error;
}
},
});
}
@@ -0,0 +1,114 @@
import {
TASK_START_SCHEMA,
InvalidTaskStartError,
TaskStartFenceRejectedError,
TaskStartNotFoundError,
TaskStartUnavailableError,
createTaskStartResponseBody,
parseTaskStartRequestBody,
type TaskStartRepository,
} from '@qinglong/runtime-core/task-start';
import type { ClusterControlAdmissionResponse } from '../transport/httpSurface';
import type {
ClusterControlAuthorizedOperationRequest,
ClusterControlRouteDefinition,
ClusterControlRouteParameters,
} from '../transport/routeRegistry';
export const CLUSTER_CONTROL_TASK_START_ROUTE = Object.freeze({
method: 'POST' as const,
path: '/api/v3/projects/{projectId}/tasks/{taskId}/runs',
operationId: 'task.start',
permission: 'run.start',
projectParameter: 'projectId',
});
export type ClusterTaskStartIdFactory = () => string;
function response(
statusCode: number,
body: Readonly<Record<string, unknown>>,
): ClusterControlAdmissionResponse {
return Object.freeze({ statusCode, body: Object.freeze(body) });
}
export function createClusterControlTaskStartRoute(
repository: TaskStartRepository,
createId: ClusterTaskStartIdFactory,
): Readonly<ClusterControlRouteDefinition> {
if (
!repository ||
typeof repository.startTask !== 'function' ||
typeof createId !== 'function'
) {
throw new TypeError('Cluster-control Task start route is invalid');
}
return Object.freeze({
...CLUSTER_CONTROL_TASK_START_ROUTE,
async handle(
authorized: ClusterControlAuthorizedOperationRequest,
parameters: ClusterControlRouteParameters,
) {
let body;
try {
body = parseTaskStartRequestBody(authorized.request.body);
} catch (error) {
if (error instanceof InvalidTaskStartError) {
return response(400, {
code: 'invalid_task_start_request',
schema: TASK_START_SCHEMA,
});
}
return response(503, { code: 'task_start_unavailable' });
}
const projectId = authorized.projectId;
const taskId = parameters.taskId;
if (
projectId === null ||
typeof taskId !== 'string' ||
taskId.length < 1 ||
!authorized.policyFence ||
authorized.policyFence.bindingVersion === null
) {
return response(503, { code: 'task_start_unavailable' });
}
try {
const result = await repository.startTask({
projectId,
taskId,
mutationId: body.mutationId,
expectedRevision: body.expectedRevision,
expectedContentDigest: body.expectedContentDigest,
runId: createId(),
attemptId: createId(),
createdEventId: createId(),
queuedEventId: createId(),
subject: authorized.principal.subject,
policyFence: authorized.policyFence,
});
return response(
result.status === 'accepted' ? 202 : 200,
createTaskStartResponseBody(result),
);
} catch (error) {
if (error instanceof TaskStartNotFoundError) {
return response(404, { code: 'task_not_found' });
}
if (error instanceof TaskStartFenceRejectedError) {
return response(409, {
code: 'task_start_fence_rejected',
reason: error.reason,
});
}
if (
error instanceof InvalidTaskStartError ||
error instanceof TaskStartUnavailableError
) {
return response(503, { code: 'task_start_unavailable' });
}
return response(503, { code: 'task_start_unavailable' });
}
},
});
}