-- 291_study_memo_card_jobs.sql -- card_extract 비동기 작업 큐 (231_study_question_jobs.sql 복제 + 다형 소스). -- 라이프사이클: pending -> processing -> completed | failed | skipped -- error_code 권장값: parse_fail / llm_timeout / unknown (재시도 대상), -- all_dropped (0장 생성, completed 로 종결해 재추출 차단), -- no_ready_explanation (skipped, 비재시도). -- source_question_id 직접 FK 대신 source_kind/source_id 다형 참조 (question|subject_note|document). -- source_version = 추출 대상 study_questions.ai_explanation_generated_at (버전 멱등키) — -- 폴러의 NOT EXISTS(... AND source_version=현재버전) 가 같은 버전 재추출을 차단. CREATE TABLE IF NOT EXISTS study_memo_card_jobs ( id BIGSERIAL PRIMARY KEY, user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE, source_kind VARCHAR(40) NOT NULL, source_id BIGINT NOT NULL, source_version TIMESTAMPTZ, kind VARCHAR(40) NOT NULL, status VARCHAR(20) NOT NULL DEFAULT 'pending', attempts SMALLINT NOT NULL DEFAULT 0, max_attempts SMALLINT NOT NULL DEFAULT 2, error_code VARCHAR(40), error_message TEXT, payload JSONB, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), started_at TIMESTAMPTZ, completed_at TIMESTAMPTZ );