From 0714b2c81a843f85c9a83b684a18981a6ea7d1c9 Mon Sep 17 00:00:00 2001 From: Daan Meijer Date: Fri, 9 Oct 2026 00:19:51 +0200 Subject: [PATCH] Rebuild: a dedicated Postgres for development (its own database, as in production) The shared database's public schema leaked the old indexer's tables into the generated schema. Co-Authored-By: Claude Opus 5.5 --- config/database.ts | 2 - database/schema.ts | 702 --------------------------------------------- start/env.ts | 1 - 3 files changed, 705 deletions(-) diff --git a/config/database.ts b/config/database.ts index 6289d14..defb37d 100644 --- a/config/database.ts +++ b/config/database.ts @@ -18,8 +18,6 @@ const dbConfig = defineConfig({ password: env.get('DB_PASSWORD'), database: env.get('DB_DATABASE'), }, - // Local development may share a database, in its own schema (DB_SEARCH_PATH=rebuild). - ...(env.get('DB_SEARCH_PATH') ? { searchPath: env.get('DB_SEARCH_PATH')!.split(',') } : {}), pool: { min: 0, max: env.get('DB_POOL_MAX', 10) }, migrations: { naturalSort: true, diff --git a/database/schema.ts b/database/schema.ts index a3dafb8..3eb293a 100644 --- a/database/schema.ts +++ b/database/schema.ts @@ -32,367 +32,6 @@ export class AuthAccessTokenSchema extends BaseModel { declare updatedAt: DateTime | null } -export class AuthAccessTokenSchema extends BaseModel { - static $columns = ['abilities', 'createdAt', 'expiresAt', 'hash', 'id', 'lastUsedAt', 'name', 'tokenableId', 'type', 'updatedAt'] as const - $columns = AuthAccessTokenSchema.$columns - @column() - declare abilities: string - @column.dateTime({ autoCreate: true }) - declare createdAt: DateTime | null - @column.dateTime() - declare expiresAt: DateTime | null - @column() - declare hash: string - @column({ isPrimary: true }) - declare id: number - @column.dateTime() - declare lastUsedAt: DateTime | null - @column() - declare name: string | null - @column() - declare tokenableId: number - @column() - declare type: string - @column.dateTime({ autoCreate: true, autoUpdate: true }) - declare updatedAt: DateTime | null -} - -export class BinarySchema extends BaseModel { - static $columns = ['awaitingInspection', 'completedAt', 'conflictedAt', 'fileId', 'fileKey', 'firstSeenAt', 'groups', 'id', 'lastSeenAt', 'md516K', 'name', 'parentBinaryId', 'partCount', 'postedAt', 'poster', 'realName', 'releaseId', 'size', 'splitAt', 'subject', 'totalParts'] as const - $columns = BinarySchema.$columns - @column() - declare awaitingInspection: boolean | null - @column.dateTime() - declare completedAt: DateTime | null - @column.dateTime() - declare conflictedAt: DateTime | null - @column() - declare fileId: bigint | number | null - @column() - declare fileKey: string - @column.dateTime() - declare firstSeenAt: DateTime - @column() - declare groups: any - @column({ isPrimary: true }) - declare id: bigint | number - @column.dateTime() - declare lastSeenAt: DateTime - @column() - declare md516K: string | null - @column() - declare name: string - @column() - declare parentBinaryId: bigint | number | null - @column() - declare partCount: number | null - @column.dateTime() - declare postedAt: DateTime | null - @column() - declare poster: string - @column() - declare realName: string | null - @column() - declare releaseId: bigint | number | null - @column() - declare size: bigint | number | null - @column.dateTime() - declare splitAt: DateTime | null - @column() - declare subject: string - @column() - declare totalParts: number -} - -export class DeferredFileSchema extends BaseModel { - static $columns = ['articleCount', 'bytes', 'contentType', 'encrypted', 'error', 'fileKey', 'firstArticle', 'firstMessageId', 'firstSeenAt', 'groupName', 'id', 'lastArticle', 'lastSeenAt', 'name', 'postedAt', 'poster', 'processedAt', 'sampledPart', 'size', 'status', 'subject', 'totalParts', 'yencName'] as const - $columns = DeferredFileSchema.$columns - @column() - declare articleCount: number - @column() - declare bytes: bigint | number - @column() - declare contentType: string | null - @column() - declare encrypted: boolean | null - @column() - declare error: string | null - @column() - declare fileKey: string - @column() - declare firstArticle: bigint | number - @column() - declare firstMessageId: string - @column.dateTime() - declare firstSeenAt: DateTime - @column() - declare groupName: string - @column({ isPrimary: true }) - declare id: bigint | number - @column() - declare lastArticle: bigint | number - @column.dateTime() - declare lastSeenAt: DateTime - @column() - declare name: string - @column.dateTime() - declare postedAt: DateTime | null - @column() - declare poster: string - @column.dateTime() - declare processedAt: DateTime | null - @column() - declare sampledPart: number | null - @column() - declare size: bigint | number | null - @column() - declare status: string - @column() - declare subject: string - @column() - declare totalParts: number | null - @column() - declare yencName: string | null -} - -export class DeferredRangeSchema extends BaseModel { - static $columns = ['articleCount', 'bytes', 'createdAt', 'expandedAt', 'firstArticle', 'groupName', 'id', 'lastArticle'] as const - $columns = DeferredRangeSchema.$columns - @column() - declare articleCount: number - @column() - declare bytes: bigint | number - @column.dateTime({ autoCreate: true }) - declare createdAt: DateTime - @column.dateTime() - declare expandedAt: DateTime | null - @column() - declare firstArticle: bigint | number - @column() - declare groupName: string - @column({ isPrimary: true }) - declare id: bigint | number - @column() - declare lastArticle: bigint | number -} - -export class DroppedReleaseSchema extends BaseModel { - static $columns = ['droppedAt', 'reason', 'releaseKey'] as const - $columns = DroppedReleaseSchema.$columns - @column.dateTime() - declare droppedAt: DateTime - @column() - declare reason: string - @column({ isPrimary: true }) - declare releaseKey: string -} - -export class FetchRangeSchema extends BaseModel { - static $columns = ['backfill', 'createdAt', 'endId', 'error', 'groupId', 'id', 'requeues', 'startId', 'status', 'updatedAt'] as const - $columns = FetchRangeSchema.$columns - @column() - declare backfill: boolean - @column.dateTime({ autoCreate: true }) - declare createdAt: DateTime - @column() - declare endId: bigint | number - @column() - declare error: string | null - @column() - declare groupId: number - @column({ isPrimary: true }) - declare id: bigint | number - @column() - declare requeues: number - @column() - declare startId: bigint | number - @column() - declare status: string - @column.dateTime({ autoCreate: true, autoUpdate: true }) - declare updatedAt: DateTime -} - -export class FileDetailSchema extends BaseModel { - static $columns = ['archive', 'contentType', 'fileId'] as const - $columns = FileDetailSchema.$columns - @column() - declare archive: any | null - @column() - declare contentType: string | null - @column({ isPrimary: true }) - declare fileId: bigint | number -} - -export class FileKeySchema extends BaseModel { - static $columns = ['keyHash'] as const - $columns = FileKeySchema.$columns - @column({ isPrimary: true }) - declare keyHash: bigint | number -} - -export class FileKeysFillSchema extends BaseModel { - static $columns = ['complete', 'id', 'nextId', 'untilId', 'updatedAt'] as const - $columns = FileKeysFillSchema.$columns - @column() - declare complete: boolean - @column({ isPrimary: true }) - declare id: number - @column() - declare nextId: bigint | number - @column() - declare untilId: bigint | number | null - @column.dateTime({ autoCreate: true, autoUpdate: true }) - declare updatedAt: DateTime -} - -export class FileSchema extends BaseModel { - static $columns = ['archive', 'contentType', 'createdAt', 'date', 'fileKey', 'filename', 'firstMessageId', 'groups', 'id', 'parts', 'poster', 'realName', 'releaseId', 'segments', 'size', 'updatedAt'] as const - $columns = FileSchema.$columns - @column() - declare archive: any | null - @column() - declare contentType: string | null - @column.dateTime({ autoCreate: true }) - declare createdAt: DateTime | null - @column() - declare date: bigint | number - @column() - declare fileKey: string | null - @column() - declare filename: string - @column() - declare firstMessageId: string | null - @column() - declare groups: any | null - @column({ isPrimary: true }) - declare id: bigint | number - @column() - declare parts: number - @column() - declare poster: string - @column() - declare realName: string | null - @column() - declare releaseId: bigint | number | null - @column() - declare segments: Buffer - @column() - declare size: bigint | number | null - @column.dateTime({ autoCreate: true, autoUpdate: true }) - declare updatedAt: DateTime | null -} - -export class FilesP0Schema extends BaseModel { - static $columns = ['archive', 'contentType', 'createdAt', 'date', 'fileKey', 'filename', 'firstMessageId', 'groups', 'id', 'parts', 'poster', 'realName', 'releaseId', 'segments', 'size', 'updatedAt'] as const - $columns = FilesP0Schema.$columns - @column() - declare archive: any | null - @column() - declare contentType: string | null - @column.dateTime({ autoCreate: true }) - declare createdAt: DateTime | null - @column() - declare date: bigint | number - @column() - declare fileKey: string | null - @column() - declare filename: string - @column() - declare firstMessageId: string | null - @column() - declare groups: any | null - @column({ isPrimary: true }) - declare id: bigint | number - @column() - declare parts: number - @column() - declare poster: string - @column() - declare realName: string | null - @column() - declare releaseId: bigint | number | null - @column() - declare segments: Buffer - @column() - declare size: bigint | number | null - @column.dateTime({ autoCreate: true, autoUpdate: true }) - declare updatedAt: DateTime | null -} - -export class FilesP1000000Schema extends BaseModel { - static $columns = ['archive', 'contentType', 'createdAt', 'date', 'fileKey', 'filename', 'firstMessageId', 'groups', 'id', 'parts', 'poster', 'realName', 'releaseId', 'segments', 'size', 'updatedAt'] as const - $columns = FilesP1000000Schema.$columns - @column() - declare archive: any | null - @column() - declare contentType: string | null - @column.dateTime({ autoCreate: true }) - declare createdAt: DateTime | null - @column() - declare date: bigint | number - @column() - declare fileKey: string | null - @column() - declare filename: string - @column() - declare firstMessageId: string | null - @column() - declare groups: any | null - @column({ isPrimary: true }) - declare id: bigint | number - @column() - declare parts: number - @column() - declare poster: string - @column() - declare realName: string | null - @column() - declare releaseId: bigint | number | null - @column() - declare segments: Buffer - @column() - declare size: bigint | number | null - @column.dateTime({ autoCreate: true, autoUpdate: true }) - declare updatedAt: DateTime | null -} - -export class FilesP5000000Schema extends BaseModel { - static $columns = ['archive', 'contentType', 'createdAt', 'date', 'fileKey', 'filename', 'firstMessageId', 'groups', 'id', 'parts', 'poster', 'realName', 'releaseId', 'segments', 'size', 'updatedAt'] as const - $columns = FilesP5000000Schema.$columns - @column() - declare archive: any | null - @column() - declare contentType: string | null - @column.dateTime({ autoCreate: true }) - declare createdAt: DateTime | null - @column() - declare date: bigint | number - @column() - declare fileKey: string | null - @column() - declare filename: string - @column() - declare firstMessageId: string | null - @column() - declare groups: any | null - @column({ isPrimary: true }) - declare id: bigint | number - @column() - declare parts: number - @column() - declare poster: string - @column() - declare realName: string | null - @column() - declare releaseId: bigint | number | null - @column() - declare segments: Buffer - @column() - declare size: bigint | number | null - @column.dateTime({ autoCreate: true, autoUpdate: true }) - declare updatedAt: DateTime | null -} - export class FragmentSchema extends BaseModel { static $columns = ['articleNumber', 'fileKey', 'id', 'rangeId', 'segment'] as const $columns = FragmentSchema.$columns @@ -429,42 +68,6 @@ export class GroupSchema extends BaseModel { declare priority: number } -export class GroupSchema extends BaseModel { - static $columns = ['active', 'backfillNextId', 'backfillUntilId', 'createdAt', 'fetchBodies', 'id', 'lastIndexedId', 'lastQueuedId', 'name', 'updatedAt'] as const - $columns = GroupSchema.$columns - @column() - declare active: boolean - @column() - declare backfillNextId: bigint | number | null - @column() - declare backfillUntilId: bigint | number | null - @column.dateTime({ autoCreate: true }) - declare createdAt: DateTime | null - @column() - declare fetchBodies: boolean - @column({ isPrimary: true }) - declare id: number - @column() - declare lastIndexedId: bigint | number | null - @column() - declare lastQueuedId: bigint | number - @column() - declare name: string - @column.dateTime({ autoCreate: true, autoUpdate: true }) - declare updatedAt: DateTime | null -} - -export class InspectionQueueSchema extends BaseModel { - static $columns = ['fileId', 'priority', 'queuedAt'] as const - $columns = InspectionQueueSchema.$columns - @column({ isPrimary: true }) - declare fileId: bigint | number - @column() - declare priority: number - @column.dateTime() - declare queuedAt: DateTime -} - export class NodeAccessTokenSchema extends BaseModel { static $columns = ['abilities', 'createdAt', 'expiresAt', 'hash', 'id', 'lastUsedAt', 'name', 'tokenableId', 'type', 'updatedAt'] as const $columns = NodeAccessTokenSchema.$columns @@ -503,52 +106,6 @@ export class NodeSchema extends BaseModel { declare name: string } -export class PartConflictSchema extends BaseModel { - static $columns = ['articleNumber', 'binaryId', 'bytes', 'fileCrc32', 'md516K', 'messageId', 'number', 'partSize', 'pcrc32'] as const - $columns = PartConflictSchema.$columns - @column() - declare articleNumber: bigint | number | null - @column({ isPrimary: true }) - declare binaryId: bigint | number - @column() - declare bytes: number - @column() - declare fileCrc32: string | null - @column() - declare md516K: string | null - @column() - declare messageId: string - @column() - declare number: number - @column() - declare partSize: number | null - @column() - declare pcrc32: string | null -} - -export class PartSchema extends BaseModel { - static $columns = ['articleNumber', 'binaryId', 'bytes', 'fileCrc32', 'md516K', 'messageId', 'number', 'partSize', 'pcrc32'] as const - $columns = PartSchema.$columns - @column() - declare articleNumber: bigint | number | null - @column({ isPrimary: true }) - declare binaryId: bigint | number - @column() - declare bytes: number - @column() - declare fileCrc32: string | null - @column() - declare md516K: string | null - @column() - declare messageId: string - @column() - declare number: number - @column() - declare partSize: number | null - @column() - declare pcrc32: string | null -} - export class ProbeCandidateSchema extends BaseModel { static $columns = ['createdAt', 'file', 'id', 'kind', 'messageId', 'releaseId', 'status'] as const $columns = ProbeCandidateSchema.$columns @@ -628,32 +185,6 @@ export class ReleaseChunkSchema extends BaseModel { declare segments: number } -export class ReleaseDirtySchema extends BaseModel { - static $columns = ['releaseId'] as const - $columns = ReleaseDirtySchema.$columns - @column() - declare releaseId: bigint | number -} - -export class ReleaseFileSchema extends BaseModel { - static $columns = ['md5', 'md516K', 'name', 'par2FileId', 'releaseId', 'setId', 'size'] as const - $columns = ReleaseFileSchema.$columns - @column() - declare md5: string | null - @column() - declare md516K: string - @column() - declare name: string - @column() - declare par2FileId: string - @column({ isPrimary: true }) - declare releaseId: bigint | number - @column() - declare setId: string | null - @column() - declare size: bigint | number -} - export class ReleaseSchema extends BaseModel { static $columns = ['bytes', 'chunks', 'complete', 'fileTotal', 'files', 'firstArticle', 'firstSeenAt', 'groups', 'hasPar2', 'id', 'lastArticle', 'lastSeenAt', 'name', 'postedAt', 'poster', 'readable', 'releaseKey', 'segments', 'settledAt', 'source'] as const $columns = ReleaseSchema.$columns @@ -699,57 +230,6 @@ export class ReleaseSchema extends BaseModel { declare source: string } -export class ReleaseSchema extends BaseModel { - static $columns = ['category', 'complete', 'container', 'contents', 'contentsWalkedAt', 'encrypted', 'extensions', 'fileCount', 'fileTotal', 'firstSeenAt', 'groups', 'id', 'lastSeenAt', 'name', 'password', 'passwordSource', 'postedAt', 'poster', 'releaseKey', 'searchFiles', 'searchText', 'size', 'source'] as const - $columns = ReleaseSchema.$columns - @column() - declare category: number | null - @column() - declare complete: boolean - @column() - declare container: string | null - @column() - declare contents: any | null - @column.dateTime() - declare contentsWalkedAt: DateTime | null - @column() - declare encrypted: boolean | null - @column() - declare extensions: any | null - @column() - declare fileCount: number - @column() - declare fileTotal: number | null - @column.dateTime() - declare firstSeenAt: DateTime - @column() - declare groups: any - @column({ isPrimary: true }) - declare id: bigint | number - @column.dateTime() - declare lastSeenAt: DateTime - @column() - declare name: string - @column({ serializeAs: null }) - declare password: string | null - @column() - declare passwordSource: string | null - @column.dateTime() - declare postedAt: DateTime | null - @column() - declare poster: string | null - @column() - declare releaseKey: string - @column() - declare searchFiles: string | null - @column() - declare searchText: string | null - @column() - declare size: bigint | number - @column() - declare source: string | null -} - export class RuleCountSchema extends BaseModel { static $columns = ['articles', 'files', 'key', 'rangeId', 'rule'] as const $columns = RuleCountSchema.$columns @@ -801,188 +281,6 @@ export class RuleSetSchema extends BaseModel { declare version: number } -export class SeedNodeSchema extends BaseModel { - static $columns = ['createdAt', 'disabled', 'id', 'lastSeenAt', 'name', 'tokenHash'] as const - $columns = SeedNodeSchema.$columns - @column.dateTime({ autoCreate: true }) - declare createdAt: DateTime - @column() - declare disabled: boolean - @column({ isPrimary: true }) - declare id: number - @column.dateTime() - declare lastSeenAt: DateTime | null - @column() - declare name: string - @column() - declare tokenHash: string -} - -export class SeedRangeSchema extends BaseModel { - static $columns = ['attempts', 'createdAt', 'doneAt', 'endId', 'error', 'files', 'fragments', 'groupName', 'headers', 'heartbeatAt', 'id', 'leasedAt', 'nextId', 'nodeId', 'priority', 'startId', 'status'] as const - $columns = SeedRangeSchema.$columns - @column() - declare attempts: number - @column.dateTime({ autoCreate: true }) - declare createdAt: DateTime - @column.dateTime() - declare doneAt: DateTime | null - @column() - declare endId: bigint | number - @column() - declare error: string | null - @column() - declare files: bigint | number - @column() - declare fragments: bigint | number - @column() - declare groupName: string - @column() - declare headers: bigint | number - @column.dateTime() - declare heartbeatAt: DateTime | null - @column({ isPrimary: true }) - declare id: bigint | number - @column.dateTime() - declare leasedAt: DateTime | null - @column() - declare nextId: bigint | number - @column() - declare nodeId: number | null - @column() - declare priority: number - @column() - declare startId: bigint | number - @column() - declare status: string -} - -export class SfvEntrySchema extends BaseModel { - static $columns = ['crc', 'name', 'postedAt', 'poster', 'releaseId'] as const - $columns = SfvEntrySchema.$columns - @column() - declare crc: string - @column() - declare name: string - @column.dateTime() - declare postedAt: DateTime | null - @column() - declare poster: string | null - @column({ isPrimary: true }) - declare releaseId: bigint | number -} - -export class SignatureProbeSchema extends BaseModel { - static $columns = ['groupName', 'probedAt', 'releaseId', 'tool'] as const - $columns = SignatureProbeSchema.$columns - @column() - declare groupName: string - @column.dateTime() - declare probedAt: DateTime - @column({ isPrimary: true }) - declare releaseId: bigint | number - @column() - declare tool: string -} - -export class SpotSchema extends BaseModel { - static $columns = ['articleNumber', 'category', 'createdAt', 'description', 'detailsAt', 'error', 'groupName', 'image', 'keyId', 'messageId', 'nzbReadAt', 'postedAt', 'poster', 'processedAt', 'releaseId', 'size', 'spotterId', 'status', 'subcats', 'tag', 'title', 'verified', 'website'] as const - $columns = SpotSchema.$columns - @column() - declare articleNumber: bigint | number | null - @column() - declare category: number | null - @column.dateTime({ autoCreate: true }) - declare createdAt: DateTime - @column() - declare description: string | null - @column.dateTime() - declare detailsAt: DateTime | null - @column() - declare error: string | null - @column() - declare groupName: string - @column() - declare image: any | null - @column() - declare keyId: number | null - @column({ isPrimary: true }) - declare messageId: string - @column.dateTime() - declare nzbReadAt: DateTime | null - @column.dateTime() - declare postedAt: DateTime | null - @column() - declare poster: string - @column.dateTime() - declare processedAt: DateTime | null - @column() - declare releaseId: bigint | number | null - @column() - declare size: bigint | number | null - @column() - declare spotterId: string | null - @column() - declare status: string - @column() - declare subcats: any | null - @column() - declare tag: string | null - @column() - declare title: string - @column() - declare verified: boolean | null - @column() - declare website: string | null -} - -export class StagedSegmentSchema extends BaseModel { - static $columns = ['counterKey', 'fileKey', 'segments', 'stagedAt'] as const - $columns = StagedSegmentSchema.$columns - @column() - declare counterKey: string | null - @column({ isPrimary: true }) - declare fileKey: string - @column() - declare segments: any - @column.dateTime() - declare stagedAt: DateTime -} - -export class UploadSignatureSchema extends BaseModel { - static $columns = ['dropped', 'groupName', 'named', 'probed', 'tool', 'updatedAt'] as const - $columns = UploadSignatureSchema.$columns - @column() - declare dropped: boolean - @column() - declare groupName: string - @column() - declare named: number - @column() - declare probed: number - @column({ isPrimary: true }) - declare tool: string - @column.dateTime({ autoCreate: true, autoUpdate: true }) - declare updatedAt: DateTime -} - -export class UserSchema extends BaseModel { - static $columns = ['createdAt', 'email', 'fullName', 'id', 'password', 'updatedAt'] as const - $columns = UserSchema.$columns - @column.dateTime({ autoCreate: true }) - declare createdAt: DateTime - @column() - declare email: string - @column() - declare fullName: string | null - @column({ isPrimary: true }) - declare id: number - @column({ serializeAs: null }) - declare password: string - @column.dateTime({ autoCreate: true, autoUpdate: true }) - declare updatedAt: DateTime | null -} - export class UserSchema extends BaseModel { static $columns = ['createdAt', 'email', 'fullName', 'id', 'password', 'updatedAt'] as const $columns = UserSchema.$columns diff --git a/start/env.ts b/start/env.ts index 362f1dd..1262ffb 100644 --- a/start/env.ts +++ b/start/env.ts @@ -32,7 +32,6 @@ export default await Env.create(new URL('../', import.meta.url), { DB_PASSWORD: Env.schema.string.optional(), DB_DATABASE: Env.schema.string(), DB_POOL_MAX: Env.schema.number.optional(), - DB_SEARCH_PATH: Env.schema.string.optional(), // Tablespace for the chunk store (the HDD on homelab). CHUNK_TABLESPACE: Env.schema.string.optional(), DB_DEBUG: Env.schema.boolean.optional(),