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,35 @@
|
||||
import type { DatabaseSync } from 'node:sqlite';
|
||||
|
||||
type Row = Record<string, unknown>;
|
||||
|
||||
function projectId(row: Row): string {
|
||||
const value = row.projectId;
|
||||
if (typeof value !== 'string') {
|
||||
throw new TypeError('Local instance authority Project is invalid');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
export function resolveLocalInstanceAuthorityProjectId(
|
||||
client: DatabaseSync,
|
||||
): string | null {
|
||||
const claimed = client
|
||||
.prepare(
|
||||
`SELECT "project_id" AS "projectId"
|
||||
FROM "QingLong3LocalOwnerBootstrapChallenges"
|
||||
WHERE "consumed_at_ms" IS NOT NULL
|
||||
ORDER BY "consumed_at_ms" ASC, "project_id" ASC, "version" ASC
|
||||
LIMIT 1`,
|
||||
)
|
||||
.get() as Row | undefined;
|
||||
if (claimed) return projectId(claimed);
|
||||
const fallback = client
|
||||
.prepare(
|
||||
`SELECT "id" AS "projectId"
|
||||
FROM "QingLong3Projects"
|
||||
WHERE "id" = 'default'
|
||||
LIMIT 1`,
|
||||
)
|
||||
.get() as Row | undefined;
|
||||
return fallback ? projectId(fallback) : null;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import type { DatabaseSync } from 'node:sqlite';
|
||||
|
||||
export const MAX_LOCAL_SQLITE_PENDING_OPERATIONS = 256;
|
||||
|
||||
/**
|
||||
* Owns the one synchronous SQLite connection, its bounded async admission
|
||||
* queue, and its close fence. Narrow repositories share this authority rather
|
||||
* than growing one public god repository or opening sibling connections.
|
||||
*/
|
||||
export class LocalSqliteOperationAuthority {
|
||||
private tail: Promise<void> = Promise.resolve();
|
||||
private pending = 0;
|
||||
private accepting = true;
|
||||
private closePromise?: Promise<void>;
|
||||
|
||||
constructor(readonly client: DatabaseSync) {}
|
||||
|
||||
enqueue<T>(
|
||||
work: () => Promise<T>,
|
||||
rejection: (reason: 'closed' | 'busy') => Error,
|
||||
): Promise<T> {
|
||||
if (!this.accepting) return Promise.reject(rejection('closed'));
|
||||
if (this.pending >= MAX_LOCAL_SQLITE_PENDING_OPERATIONS) {
|
||||
return Promise.reject(rejection('busy'));
|
||||
}
|
||||
this.pending += 1;
|
||||
const result = this.tail.then(work, work);
|
||||
this.tail = result.then(
|
||||
() => undefined,
|
||||
() => undefined,
|
||||
);
|
||||
return result.finally(() => {
|
||||
this.pending -= 1;
|
||||
});
|
||||
}
|
||||
|
||||
close(): Promise<void> {
|
||||
if (this.closePromise) return this.closePromise;
|
||||
this.accepting = false;
|
||||
this.closePromise = this.tail.then(() => {
|
||||
if (this.client.isOpen) this.client.close();
|
||||
});
|
||||
return this.closePromise;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user