openreader/tests/unit/document-blob-lease.vitest.spec.ts
Richard R 358a56cc9a refactor: implement modular monorepo packages
- 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
2026-06-13 13:51:18 -06:00

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);
});
});