0c99693002
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
57 lines
4.0 KiB
SQL
57 lines
4.0 KiB
SQL
-- 스캔 기능: 잡 모델 + 배치 + 에이전트 생존 (plan: scan-feature-build r3)
|
|
-- 웹(fastapi)=intent/명령, 호스트 스캔 에이전트=결과. 싱글톤 스캐너 직렬화.
|
|
-- 주: 러너 규약상 이 파일은 schema_migrations 를 건드리지 않음(스탬프는 외부). BEGIN/COMMIT 없음.
|
|
-- 순서: 테이블 먼저 → 시드 → 인덱스 (인덱스 실패가 테이블 생성 막지 않게).
|
|
|
|
-- 잡: 한 스캔 세션 = 한 논리 문서 (배치 N개 → 합본 1 PDF → Inbox)
|
|
CREATE TABLE IF NOT EXISTS scan_jobs (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
title TEXT NOT NULL, -- 사람 입력 제목 (commit 시 documents.title 로 전파)
|
|
settings JSONB NOT NULL DEFAULT '{}'::jsonb, -- mode/resolution/source(ADF Duplex) 등 스캔 프로파일
|
|
status TEXT NOT NULL DEFAULT 'draft', -- draft|queued|ready|scanning|assembling|preview|committing|committed|failed|canceled
|
|
batch_count INTEGER NOT NULL DEFAULT 0, -- 스캔 완료 배치 수
|
|
page_count INTEGER, -- 최종 합본 페이지 수 (assembling 후)
|
|
last_activity_at TIMESTAMPTZ, -- ready 휴지 벽시계 idle 타임아웃 기준 (방치 데드락 방지)
|
|
last_progress_at TIMESTAMPTZ, -- 잡 진행 갱신 (에이전트 생존과 분리)
|
|
staging_path TEXT, -- 호스트 로컬 잡 스테이징 디렉토리
|
|
nas_staging_path TEXT, -- NAS .scan-staging 합본 경로 (B안 미리보기/commit 소스)
|
|
inbox_path TEXT, -- 최종 PKM/Inbox 경로 (commit 후)
|
|
file_hash CHAR(64), -- 합본 sha256 = 정체성/멱등 커밋 키 (commit 시 채움)
|
|
doc_id BIGINT REFERENCES documents(id) ON DELETE SET NULL, -- commit 후 연결 (title 전파)
|
|
error TEXT, -- failed 사유 (no-silent)
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- 배치: 스캔 1회(ADF 한 묶음) 단위. batch_seq = 결합 순서(글롭 정렬 아님).
|
|
CREATE TABLE IF NOT EXISTS scan_job_batches (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
job_id BIGINT REFERENCES scan_jobs(id) ON DELETE CASCADE NOT NULL,
|
|
batch_seq INTEGER NOT NULL, -- 1-based 결합 순서
|
|
staging_path TEXT, -- 이 배치 PDF (호스트 로컬)
|
|
page_count INTEGER,
|
|
status TEXT NOT NULL DEFAULT 'scanned', -- scanned | discarded (잼 폐기 후 재스캔)
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
UNIQUE (job_id, batch_seq)
|
|
);
|
|
|
|
-- 에이전트 생존: 싱글톤 1행. 잡 진행(last_progress_at)과 분리 — queued 잡 stale 오탐 방지.
|
|
CREATE TABLE IF NOT EXISTS scan_agent_status (
|
|
id INTEGER PRIMARY KEY DEFAULT 1 CHECK (id = 1), -- 단일 행 강제
|
|
last_heartbeat TIMESTAMPTZ,
|
|
agent_version TEXT,
|
|
current_job_id BIGINT REFERENCES scan_jobs(id) ON DELETE SET NULL,
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
INSERT INTO scan_agent_status (id) VALUES (1) ON CONFLICT (id) DO NOTHING; -- 시드 1행
|
|
|
|
-- 활성 잡 락: 스캐너 싱글톤 → in-progress 잡은 전체에서 1개만(나머지 queued).
|
|
-- 상수 TRUE 에 unique + in-progress 필터 = 그 상태 행 최대 1개 강제.
|
|
CREATE UNIQUE INDEX IF NOT EXISTS uq_scan_jobs_single_active
|
|
ON scan_jobs ((TRUE))
|
|
WHERE status IN ('ready','scanning','assembling','preview','committing');
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_scan_jobs_queued ON scan_jobs (created_at) WHERE status = 'queued';
|
|
CREATE INDEX IF NOT EXISTS idx_scan_jobs_file_hash ON scan_jobs (file_hash) WHERE file_hash IS NOT NULL;
|
|
CREATE INDEX IF NOT EXISTS idx_scan_job_batches_job ON scan_job_batches (job_id, batch_seq);
|