mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-21 18:08:20 +08:00
feat(ql3): establish 3.0 incubation baseline
This commit is contained in:
@@ -0,0 +1,529 @@
|
||||
import type {
|
||||
RunAttemptRecord,
|
||||
RunEventRecord,
|
||||
RunRecord,
|
||||
RunRetryPolicyRecord,
|
||||
} from '@qinglong/runtime-core/run-repository';
|
||||
import {
|
||||
EXECUTION_ORIGINS,
|
||||
MAX_RUN_EVENT_PAYLOAD_BYTES,
|
||||
RUN_ATTEMPT_STATUSES,
|
||||
RUN_CANCELLATION_REASONS,
|
||||
RUN_EVENT_ACTOR_TYPES,
|
||||
RUN_RETRY_SAFETIES,
|
||||
RUN_STATUSES,
|
||||
RunEventPayloadTooLargeError,
|
||||
RunRepositoryBusyError,
|
||||
RunRepositoryConstraintError,
|
||||
RunRepositoryError,
|
||||
RunRepositoryOperationError,
|
||||
assertRunRetryPolicyRecord,
|
||||
} from '@qinglong/runtime-core/run-repository';
|
||||
import type { DatabaseSync } from 'node:sqlite';
|
||||
|
||||
import {
|
||||
createSqlitePersistencePrimitives,
|
||||
isSqliteDriverError,
|
||||
sqliteDriverErrorCode,
|
||||
sqliteDriverErrorMessage,
|
||||
sqliteDriverErrorNumber,
|
||||
type SqliteQueryRow,
|
||||
} from '../storage/sqlitePersistence';
|
||||
|
||||
interface ColumnDefinition {
|
||||
readonly column: string;
|
||||
readonly property: string;
|
||||
}
|
||||
|
||||
export type QueryRow = SqliteQueryRow;
|
||||
|
||||
const RUN_SQLITE_PERSISTENCE = createSqlitePersistencePrimitives({
|
||||
invalidRowValue: (property) =>
|
||||
new RunRepositoryConstraintError(
|
||||
`Local SQLite Run row has an invalid ${property}`,
|
||||
),
|
||||
invalidJson: (property) =>
|
||||
new RunRepositoryConstraintError(
|
||||
`Local SQLite Run row has invalid ${property} JSON`,
|
||||
),
|
||||
unsupportedRowValue: (property) =>
|
||||
new RunRepositoryConstraintError(
|
||||
`Local SQLite Run row has an unsupported ${property}`,
|
||||
),
|
||||
duplicateIdentityRows: () =>
|
||||
new RunRepositoryConstraintError(
|
||||
'Local SQLite Run repository returned duplicate identity rows',
|
||||
),
|
||||
mapDriverError: mapSqliteError,
|
||||
});
|
||||
|
||||
export const RUN_COLUMNS: readonly ColumnDefinition[] = Object.freeze([
|
||||
{ column: 'id', property: 'id' },
|
||||
{ column: 'project_id', property: 'projectId' },
|
||||
{ column: 'task_id', property: 'taskId' },
|
||||
{ column: 'task_revision', property: 'taskRevision' },
|
||||
{ column: 'task_name', property: 'taskName' },
|
||||
{ column: 'task_snapshot_ref', property: 'taskSnapshotRef' },
|
||||
{ column: 'legacy_cron_id', property: 'legacyCronId' },
|
||||
{ column: 'parent_run_id', property: 'parentRunId' },
|
||||
{ column: 'retry_of_run_id', property: 'retryOfRunId' },
|
||||
{ column: 'trigger_id', property: 'triggerId' },
|
||||
{ column: 'trigger_type', property: 'triggerType' },
|
||||
{ column: 'execution_origin', property: 'executionOrigin' },
|
||||
{ column: 'execution_owner', property: 'executionOwner' },
|
||||
{ column: 'triggered_by', property: 'triggeredBy' },
|
||||
{ column: 'request_id', property: 'requestId' },
|
||||
{ column: 'scheduled_for_ms', property: 'scheduledForMs' },
|
||||
{ column: 'status', property: 'status' },
|
||||
{ column: 'version', property: 'version' },
|
||||
{ column: 'event_sequence', property: 'eventSequence' },
|
||||
{ column: 'priority', property: 'priority' },
|
||||
{ column: 'idempotency_key', property: 'idempotencyKey' },
|
||||
{ column: 'input_ref', property: 'inputRef' },
|
||||
{ column: 'output_ref', property: 'outputRef' },
|
||||
{ column: 'created_at_ms', property: 'createdAtMs' },
|
||||
{ column: 'queued_at_ms', property: 'queuedAtMs' },
|
||||
{ column: 'started_at_ms', property: 'startedAtMs' },
|
||||
{ column: 'finished_at_ms', property: 'finishedAtMs' },
|
||||
{ column: 'cancel_requested_at_ms', property: 'cancelRequestedAtMs' },
|
||||
{ column: 'cancel_reason', property: 'cancelReason' },
|
||||
{ column: 'error_code', property: 'errorCode' },
|
||||
{ column: 'error_summary', property: 'errorSummary' },
|
||||
]);
|
||||
|
||||
export const ATTEMPT_COLUMNS: readonly ColumnDefinition[] = Object.freeze([
|
||||
{ column: 'id', property: 'id' },
|
||||
{ column: 'run_id', property: 'runId' },
|
||||
{ column: 'step_run_id', property: 'stepRunId' },
|
||||
{ column: 'attempt', property: 'attempt' },
|
||||
{ column: 'status', property: 'status' },
|
||||
{ column: 'executor_type', property: 'executorType' },
|
||||
{ column: 'worker_id', property: 'workerId' },
|
||||
{ column: 'worker_session_id', property: 'workerSessionId' },
|
||||
{ column: 'worker_generation', property: 'workerGeneration' },
|
||||
{ column: 'executor_handle', property: 'executorHandle' },
|
||||
{ column: 'pid', property: 'pid' },
|
||||
{ column: 'log_artifact_id', property: 'logArtifactId' },
|
||||
{ column: 'lease_token', property: 'leaseToken' },
|
||||
{ column: 'lease_token_digest', property: 'leaseTokenDigest' },
|
||||
{ column: 'lease_generation', property: 'leaseGeneration' },
|
||||
{ column: 'lease_version', property: 'leaseVersion' },
|
||||
{ column: 'lease_expires_at_ms', property: 'leaseExpiresAtMs' },
|
||||
{ column: 'offer_id', property: 'offerId' },
|
||||
{ column: 'deadline_at_ms', property: 'deadlineAtMs' },
|
||||
{ column: 'callback_token_hash', property: 'callbackTokenHash' },
|
||||
{ column: 'callback_sequence', property: 'callbackSequence' },
|
||||
{ column: 'created_at_ms', property: 'createdAtMs' },
|
||||
{ column: 'started_at_ms', property: 'startedAtMs' },
|
||||
{ column: 'finished_at_ms', property: 'finishedAtMs' },
|
||||
{ column: 'exit_code', property: 'exitCode' },
|
||||
{ column: 'error_code', property: 'errorCode' },
|
||||
{ column: 'error_summary', property: 'errorSummary' },
|
||||
]);
|
||||
|
||||
export const EVENT_COLUMNS: readonly ColumnDefinition[] = Object.freeze([
|
||||
{ column: 'id', property: 'id' },
|
||||
{ column: 'run_id', property: 'runId' },
|
||||
{ column: 'sequence', property: 'sequence' },
|
||||
{ column: 'type', property: 'type' },
|
||||
{ column: 'dedupe_key', property: 'dedupeKey' },
|
||||
{ column: 'actor_type', property: 'actorType' },
|
||||
{ column: 'actor_id', property: 'actorId' },
|
||||
{ column: 'attempt_id', property: 'attemptId' },
|
||||
{ column: 'step_run_id', property: 'stepRunId' },
|
||||
{ column: 'payload', property: 'payload' },
|
||||
{ column: 'created_at_ms', property: 'createdAtMs' },
|
||||
]);
|
||||
|
||||
export const RETRY_POLICY_COLUMNS: readonly ColumnDefinition[] = Object.freeze([
|
||||
{ column: 'run_id', property: 'runId' },
|
||||
{ column: 'max_attempts', property: 'maxAttempts' },
|
||||
{ column: 'retry_on_lost', property: 'retryOnLost' },
|
||||
{ column: 'safety', property: 'safety' },
|
||||
{ column: 'backoff_base_ms', property: 'backoffBaseMs' },
|
||||
{ column: 'backoff_max_ms', property: 'backoffMaxMs' },
|
||||
{ column: 'next_attempt_at_ms', property: 'nextAttemptAtMs' },
|
||||
{ column: 'version', property: 'version' },
|
||||
{ column: 'created_at_ms', property: 'createdAtMs' },
|
||||
{ column: 'updated_at_ms', property: 'updatedAtMs' },
|
||||
]);
|
||||
function quoted(identifier: string): string {
|
||||
return `"${identifier}"`;
|
||||
}
|
||||
|
||||
function selectColumns(columns: readonly ColumnDefinition[]): string {
|
||||
return columns
|
||||
.map(({ column, property }) => `${quoted(column)} AS ${quoted(property)}`)
|
||||
.join(', ');
|
||||
}
|
||||
|
||||
function insertSql(
|
||||
tableName: string,
|
||||
columns: readonly ColumnDefinition[],
|
||||
): string {
|
||||
return `INSERT INTO ${quoted(tableName)} (${columns
|
||||
.map(({ column }) => quoted(column))
|
||||
.join(', ')}) VALUES (${columns.map(() => '?').join(', ')})`;
|
||||
}
|
||||
|
||||
function updateSql(
|
||||
tableName: string,
|
||||
columns: readonly ColumnDefinition[],
|
||||
predicate: string,
|
||||
): string {
|
||||
return `UPDATE ${quoted(tableName)} SET ${columns
|
||||
.slice(1)
|
||||
.map(({ column }) => `${quoted(column)} = ?`)
|
||||
.join(', ')} WHERE ${predicate}`;
|
||||
}
|
||||
|
||||
export function writeValues(
|
||||
record: object,
|
||||
columns: readonly ColumnDefinition[],
|
||||
): (string | number | bigint | Uint8Array | null)[] {
|
||||
const values = record as Record<string, unknown>;
|
||||
return columns.map(({ property }) => {
|
||||
const value = values[property];
|
||||
if (value === undefined || value === null) return null;
|
||||
if (typeof value === 'boolean') return value ? 1 : 0;
|
||||
if (
|
||||
typeof value === 'string' ||
|
||||
typeof value === 'number' ||
|
||||
typeof value === 'bigint' ||
|
||||
value instanceof Uint8Array
|
||||
) {
|
||||
return value;
|
||||
}
|
||||
throw new RunRepositoryConstraintError(
|
||||
`Local SQLite write value ${property} is invalid`,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function requiredString(row: QueryRow, property: string): string {
|
||||
return RUN_SQLITE_PERSISTENCE.requiredString(row, property);
|
||||
}
|
||||
|
||||
export function optionalString(
|
||||
row: QueryRow,
|
||||
property: string,
|
||||
): string | undefined {
|
||||
return RUN_SQLITE_PERSISTENCE.optionalString(row, property);
|
||||
}
|
||||
|
||||
export function requiredInteger(row: QueryRow, property: string): number {
|
||||
return RUN_SQLITE_PERSISTENCE.requiredInteger(row, property);
|
||||
}
|
||||
|
||||
export function requiredBlob(row: QueryRow, property: string): Buffer {
|
||||
try {
|
||||
return RUN_SQLITE_PERSISTENCE.requiredBlob(row, property);
|
||||
} catch (error) {
|
||||
if (error instanceof RunRepositoryConstraintError) {
|
||||
throw new RunRepositoryConstraintError(
|
||||
`Local SQLite row has an invalid ${property}`,
|
||||
);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export function optionalInteger(
|
||||
row: QueryRow,
|
||||
property: string,
|
||||
): number | undefined {
|
||||
return RUN_SQLITE_PERSISTENCE.optionalInteger(row, property);
|
||||
}
|
||||
|
||||
export function requiredBoolean(row: QueryRow, property: string): boolean {
|
||||
return RUN_SQLITE_PERSISTENCE.requiredBoolean(row, property);
|
||||
}
|
||||
|
||||
export function requiredJson(row: QueryRow, property: string): unknown {
|
||||
return RUN_SQLITE_PERSISTENCE.requiredJson(row, property);
|
||||
}
|
||||
|
||||
export function requiredEnum<T extends string>(
|
||||
row: QueryRow,
|
||||
property: string,
|
||||
allowed: readonly T[],
|
||||
): T {
|
||||
return RUN_SQLITE_PERSISTENCE.requiredEnum(row, property, allowed);
|
||||
}
|
||||
|
||||
function assignOptional<T extends object, K extends keyof T>(
|
||||
record: T,
|
||||
key: K,
|
||||
value: T[K] | undefined,
|
||||
): void {
|
||||
if (value !== undefined) record[key] = value;
|
||||
}
|
||||
|
||||
export function rowToRun(row: QueryRow): RunRecord {
|
||||
const run: RunRecord = {
|
||||
id: requiredString(row, 'id'),
|
||||
projectId: requiredString(row, 'projectId'),
|
||||
taskId: requiredString(row, 'taskId'),
|
||||
taskRevision: requiredString(row, 'taskRevision'),
|
||||
triggerType: requiredString(row, 'triggerType'),
|
||||
executionOrigin: requiredEnum(row, 'executionOrigin', EXECUTION_ORIGINS),
|
||||
executionOwner: requiredEnum(row, 'executionOwner', [
|
||||
'legacy',
|
||||
'runtime',
|
||||
] as const),
|
||||
status: requiredEnum(row, 'status', RUN_STATUSES),
|
||||
version: requiredInteger(row, 'version'),
|
||||
eventSequence: requiredInteger(row, 'eventSequence'),
|
||||
priority: requiredInteger(row, 'priority'),
|
||||
createdAtMs: requiredInteger(row, 'createdAtMs'),
|
||||
};
|
||||
assignOptional(run, 'taskName', optionalString(row, 'taskName'));
|
||||
assignOptional(
|
||||
run,
|
||||
'taskSnapshotRef',
|
||||
optionalString(row, 'taskSnapshotRef'),
|
||||
);
|
||||
assignOptional(run, 'legacyCronId', optionalInteger(row, 'legacyCronId'));
|
||||
assignOptional(run, 'parentRunId', optionalString(row, 'parentRunId'));
|
||||
assignOptional(run, 'retryOfRunId', optionalString(row, 'retryOfRunId'));
|
||||
assignOptional(run, 'triggerId', optionalString(row, 'triggerId'));
|
||||
assignOptional(run, 'triggeredBy', optionalString(row, 'triggeredBy'));
|
||||
assignOptional(run, 'requestId', optionalString(row, 'requestId'));
|
||||
assignOptional(run, 'scheduledForMs', optionalInteger(row, 'scheduledForMs'));
|
||||
assignOptional(run, 'idempotencyKey', optionalString(row, 'idempotencyKey'));
|
||||
assignOptional(run, 'inputRef', optionalString(row, 'inputRef'));
|
||||
assignOptional(run, 'outputRef', optionalString(row, 'outputRef'));
|
||||
assignOptional(run, 'queuedAtMs', optionalInteger(row, 'queuedAtMs'));
|
||||
assignOptional(run, 'startedAtMs', optionalInteger(row, 'startedAtMs'));
|
||||
assignOptional(run, 'finishedAtMs', optionalInteger(row, 'finishedAtMs'));
|
||||
assignOptional(
|
||||
run,
|
||||
'cancelRequestedAtMs',
|
||||
optionalInteger(row, 'cancelRequestedAtMs'),
|
||||
);
|
||||
if (row.cancelReason !== null && row.cancelReason !== undefined) {
|
||||
run.cancelReason = requiredEnum(
|
||||
row,
|
||||
'cancelReason',
|
||||
RUN_CANCELLATION_REASONS,
|
||||
);
|
||||
}
|
||||
assignOptional(run, 'errorCode', optionalString(row, 'errorCode'));
|
||||
assignOptional(run, 'errorSummary', optionalString(row, 'errorSummary'));
|
||||
return run;
|
||||
}
|
||||
|
||||
export function rowToAttempt(row: QueryRow): RunAttemptRecord {
|
||||
const attempt: RunAttemptRecord = {
|
||||
id: requiredString(row, 'id'),
|
||||
runId: requiredString(row, 'runId'),
|
||||
attempt: requiredInteger(row, 'attempt'),
|
||||
status: requiredEnum(row, 'status', RUN_ATTEMPT_STATUSES),
|
||||
executorType: requiredString(row, 'executorType'),
|
||||
callbackSequence: requiredInteger(row, 'callbackSequence'),
|
||||
createdAtMs: requiredInteger(row, 'createdAtMs'),
|
||||
};
|
||||
assignOptional(attempt, 'stepRunId', optionalString(row, 'stepRunId'));
|
||||
assignOptional(attempt, 'workerId', optionalString(row, 'workerId'));
|
||||
assignOptional(
|
||||
attempt,
|
||||
'workerSessionId',
|
||||
optionalString(row, 'workerSessionId'),
|
||||
);
|
||||
assignOptional(
|
||||
attempt,
|
||||
'workerGeneration',
|
||||
optionalInteger(row, 'workerGeneration'),
|
||||
);
|
||||
assignOptional(
|
||||
attempt,
|
||||
'executorHandle',
|
||||
optionalString(row, 'executorHandle'),
|
||||
);
|
||||
assignOptional(attempt, 'pid', optionalInteger(row, 'pid'));
|
||||
assignOptional(
|
||||
attempt,
|
||||
'logArtifactId',
|
||||
optionalString(row, 'logArtifactId'),
|
||||
);
|
||||
assignOptional(attempt, 'leaseToken', optionalString(row, 'leaseToken'));
|
||||
assignOptional(
|
||||
attempt,
|
||||
'leaseTokenDigest',
|
||||
optionalString(row, 'leaseTokenDigest'),
|
||||
);
|
||||
assignOptional(
|
||||
attempt,
|
||||
'leaseGeneration',
|
||||
optionalInteger(row, 'leaseGeneration'),
|
||||
);
|
||||
assignOptional(attempt, 'leaseVersion', optionalInteger(row, 'leaseVersion'));
|
||||
assignOptional(
|
||||
attempt,
|
||||
'leaseExpiresAtMs',
|
||||
optionalInteger(row, 'leaseExpiresAtMs'),
|
||||
);
|
||||
assignOptional(attempt, 'offerId', optionalString(row, 'offerId'));
|
||||
assignOptional(attempt, 'deadlineAtMs', optionalInteger(row, 'deadlineAtMs'));
|
||||
assignOptional(
|
||||
attempt,
|
||||
'callbackTokenHash',
|
||||
optionalString(row, 'callbackTokenHash'),
|
||||
);
|
||||
assignOptional(attempt, 'startedAtMs', optionalInteger(row, 'startedAtMs'));
|
||||
assignOptional(attempt, 'finishedAtMs', optionalInteger(row, 'finishedAtMs'));
|
||||
assignOptional(attempt, 'exitCode', optionalInteger(row, 'exitCode'));
|
||||
assignOptional(attempt, 'errorCode', optionalString(row, 'errorCode'));
|
||||
assignOptional(attempt, 'errorSummary', optionalString(row, 'errorSummary'));
|
||||
return attempt;
|
||||
}
|
||||
|
||||
function normalizePayload(payload: unknown): Readonly<Record<string, unknown>> {
|
||||
let value = payload;
|
||||
if (typeof value === 'string') {
|
||||
try {
|
||||
value = JSON.parse(value);
|
||||
} catch (error) {
|
||||
throw new RunRepositoryConstraintError(
|
||||
'Local SQLite RunEvent payload is invalid JSON',
|
||||
error,
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
||||
throw new RunRepositoryConstraintError(
|
||||
'Local SQLite RunEvent payload is not a JSON object',
|
||||
);
|
||||
}
|
||||
return value as Readonly<Record<string, unknown>>;
|
||||
}
|
||||
|
||||
export function rowToEvent(row: QueryRow): RunEventRecord {
|
||||
const event: RunEventRecord = {
|
||||
id: requiredString(row, 'id'),
|
||||
runId: requiredString(row, 'runId'),
|
||||
sequence: requiredInteger(row, 'sequence'),
|
||||
type: requiredString(row, 'type'),
|
||||
actorType: requiredEnum(row, 'actorType', RUN_EVENT_ACTOR_TYPES),
|
||||
payload: normalizePayload(row.payload),
|
||||
createdAtMs: requiredInteger(row, 'createdAtMs'),
|
||||
};
|
||||
assignOptional(event, 'dedupeKey', optionalString(row, 'dedupeKey'));
|
||||
assignOptional(event, 'actorId', optionalString(row, 'actorId'));
|
||||
assignOptional(event, 'attemptId', optionalString(row, 'attemptId'));
|
||||
assignOptional(event, 'stepRunId', optionalString(row, 'stepRunId'));
|
||||
return event;
|
||||
}
|
||||
|
||||
export function rowToRetryPolicy(row: QueryRow): RunRetryPolicyRecord {
|
||||
const policy: RunRetryPolicyRecord = {
|
||||
runId: requiredString(row, 'runId'),
|
||||
maxAttempts: requiredInteger(row, 'maxAttempts'),
|
||||
retryOnLost: requiredBoolean(row, 'retryOnLost'),
|
||||
safety: requiredEnum(row, 'safety', RUN_RETRY_SAFETIES),
|
||||
backoffBaseMs: requiredInteger(row, 'backoffBaseMs'),
|
||||
backoffMaxMs: requiredInteger(row, 'backoffMaxMs'),
|
||||
version: requiredInteger(row, 'version'),
|
||||
createdAtMs: requiredInteger(row, 'createdAtMs'),
|
||||
updatedAtMs: requiredInteger(row, 'updatedAtMs'),
|
||||
};
|
||||
assignOptional(
|
||||
policy,
|
||||
'nextAttemptAtMs',
|
||||
optionalInteger(row, 'nextAttemptAtMs'),
|
||||
);
|
||||
assertRunRetryPolicyRecord(policy);
|
||||
return policy;
|
||||
}
|
||||
|
||||
function sqliteErrorCode(error: unknown): string | undefined {
|
||||
return sqliteDriverErrorCode(error);
|
||||
}
|
||||
|
||||
function sqliteErrorNumber(error: unknown): number | undefined {
|
||||
return sqliteDriverErrorNumber(error);
|
||||
}
|
||||
|
||||
export function sqliteErrorMessage(error: unknown): string {
|
||||
return sqliteDriverErrorMessage(error);
|
||||
}
|
||||
|
||||
export function isSqliteError(error: unknown): boolean {
|
||||
return isSqliteDriverError(error);
|
||||
}
|
||||
|
||||
export function mapSqliteError(error: unknown): RunRepositoryError {
|
||||
if (error instanceof RunRepositoryError) return error;
|
||||
const baseCode = (sqliteErrorNumber(error) ?? 0) & 0xff;
|
||||
if (baseCode === 5 || baseCode === 6) {
|
||||
return new RunRepositoryBusyError(error);
|
||||
}
|
||||
if (baseCode === 19 || sqliteErrorCode(error) === 'ERR_SQLITE_CONSTRAINT') {
|
||||
return new RunRepositoryConstraintError(
|
||||
'Local SQLite Run repository constraint violation',
|
||||
error,
|
||||
);
|
||||
}
|
||||
return new RunRepositoryOperationError(error);
|
||||
}
|
||||
|
||||
export function assertEventPayloadSize(event: RunEventRecord): string {
|
||||
let serialized: string | undefined;
|
||||
try {
|
||||
serialized = JSON.stringify(event.payload);
|
||||
} catch (error) {
|
||||
throw new RunRepositoryConstraintError(
|
||||
'RunEvent payload is not JSON serializable',
|
||||
error,
|
||||
);
|
||||
}
|
||||
if (serialized === undefined) {
|
||||
throw new RunRepositoryConstraintError(
|
||||
'RunEvent payload is not JSON serializable',
|
||||
);
|
||||
}
|
||||
const bytes = Buffer.byteLength(serialized, 'utf8');
|
||||
if (bytes > MAX_RUN_EVENT_PAYLOAD_BYTES) {
|
||||
throw new RunEventPayloadTooLargeError(bytes, MAX_RUN_EVENT_PAYLOAD_BYTES);
|
||||
}
|
||||
return serialized;
|
||||
}
|
||||
|
||||
export function queryRows(
|
||||
client: DatabaseSync,
|
||||
sql: string,
|
||||
values: readonly (string | number | bigint | Uint8Array | null)[] = [],
|
||||
): QueryRow[] {
|
||||
return RUN_SQLITE_PERSISTENCE.queryRows(client, sql, values);
|
||||
}
|
||||
|
||||
export function singleRow(rows: QueryRow[]): QueryRow | null {
|
||||
return RUN_SQLITE_PERSISTENCE.singleRow(rows);
|
||||
}
|
||||
export const RUN_SELECT = selectColumns(RUN_COLUMNS);
|
||||
export const ATTEMPT_SELECT = selectColumns(ATTEMPT_COLUMNS);
|
||||
export const EVENT_SELECT = selectColumns(EVENT_COLUMNS);
|
||||
export const RETRY_POLICY_SELECT = selectColumns(RETRY_POLICY_COLUMNS);
|
||||
|
||||
export const INSERT_RUN_SQL = insertSql('Runs', RUN_COLUMNS);
|
||||
export const INSERT_ATTEMPT_SQL = insertSql('RunAttempts', ATTEMPT_COLUMNS);
|
||||
export const INSERT_EVENT_SQL = insertSql('RunEvents', EVENT_COLUMNS);
|
||||
export const INSERT_RETRY_POLICY_SQL = insertSql(
|
||||
'RunRetryPolicies',
|
||||
RETRY_POLICY_COLUMNS,
|
||||
);
|
||||
export const UPDATE_RUN_SQL = updateSql(
|
||||
'Runs',
|
||||
RUN_COLUMNS,
|
||||
'"id" = ? AND "version" = ?',
|
||||
);
|
||||
export const UPDATE_ATTEMPT_SQL = updateSql(
|
||||
'RunAttempts',
|
||||
ATTEMPT_COLUMNS,
|
||||
'"id" = ? AND "status" = ? AND "callback_sequence" = ?',
|
||||
);
|
||||
export const UPDATE_RETRY_POLICY_SQL = updateSql(
|
||||
'RunRetryPolicies',
|
||||
RETRY_POLICY_COLUMNS,
|
||||
'"run_id" = ? AND "version" = ?',
|
||||
);
|
||||
Reference in New Issue
Block a user