- Extract database schema and migrations into @openreader/database - Extract startup and orchestration scripts into @openreader/bootstrap - Move compute-worker into packages/compute-worker - Remove runtime dependency on drizzle-kit - Update Dockerfile to deploy isolated packages without merging node_modules
59 lines
2 KiB
TypeScript
59 lines
2 KiB
TypeScript
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
|
import Database from 'better-sqlite3';
|
|
import { drizzle } from 'drizzle-orm/better-sqlite3';
|
|
import * as sqliteSchema from '@openreader/database/schema-sqlite';
|
|
|
|
const holder = vi.hoisted(() => ({ db: null as unknown as ReturnType<typeof drizzle> }));
|
|
vi.mock('@openreader/database', () => ({
|
|
get db() {
|
|
return holder.db;
|
|
},
|
|
}));
|
|
|
|
import { tryAcquireDocumentBlobLease } from '../../src/lib/server/documents/blob-lease';
|
|
|
|
beforeEach(() => {
|
|
const sqlite = new Database(':memory:');
|
|
sqlite.exec(`CREATE TABLE document_blob_leases (
|
|
document_id text PRIMARY KEY NOT NULL,
|
|
lease_owner text NOT NULL,
|
|
lease_until_ms integer NOT NULL
|
|
);`);
|
|
holder.db = drizzle(sqlite, { schema: sqliteSchema });
|
|
});
|
|
|
|
describe('document blob lease', () => {
|
|
test('allows only one owner until the lease is released', async () => {
|
|
const first = await tryAcquireDocumentBlobLease('doc-1');
|
|
const blocked = await tryAcquireDocumentBlobLease('doc-1');
|
|
|
|
expect(first).not.toBeNull();
|
|
expect(blocked).toBeNull();
|
|
|
|
await first?.release();
|
|
await expect(tryAcquireDocumentBlobLease('doc-1')).resolves.not.toBeNull();
|
|
});
|
|
|
|
test('allows an expired lease to be reclaimed', async () => {
|
|
const first = await tryAcquireDocumentBlobLease('doc-1');
|
|
expect(first).not.toBeNull();
|
|
|
|
await holder.db
|
|
.update(sqliteSchema.documentBlobLeases)
|
|
.set({ leaseUntilMs: Date.now() - 1 });
|
|
const replacement = await tryAcquireDocumentBlobLease('doc-1');
|
|
|
|
expect(replacement).not.toBeNull();
|
|
expect(replacement?.owner).not.toBe(first?.owner);
|
|
|
|
// Releasing the now-stale original lease must not delete the replacement,
|
|
// since release() is scoped to the original owner.
|
|
await first?.release();
|
|
|
|
const rows = await holder.db
|
|
.select()
|
|
.from(sqliteSchema.documentBlobLeases);
|
|
expect(rows).toHaveLength(1);
|
|
expect(rows[0]?.leaseOwner).toBe(replacement?.owner);
|
|
});
|
|
});
|