PostgreSQL Logical Replication 기반 Board Post CDC
ragcenter.cdc는 source PostgreSQL의 tb_board_posts logical decoding slot을 peek → target commit → advance 순서로 처리한다. slot LSN은 local embedding과 target PostgreSQL lifecycle/COPY transaction이 성공한 뒤에만 advance한다. 따라서 embedding service, target DB, 네트워크 오류가 나면 source WAL offset이 진행되지 않고 같은 committed transaction을 재시도한다.
PostgreSQL logical decoding은
wal_level=logical, 하나 이상의 replication slot, 충분한max_wal_senders가 필요하다. replication slot은 consumer가 lagging 상태일 때 필요한 WAL을 보존하므로, 운영자는 slot lag와 WAL disk 사용량을 모니터링하고 장기간 중단된 listener를 복구하거나 의도적으로 drop해야 한다. [1]
Source DB 준비
source portal PostgreSQL DB에서 DBA가 다음을 수행한다.
wal_level=logical,max_replication_slots >= 1,max_wal_senders >= 1을 설정하고 restart한다.- source table에 stable primary key가 있는지 확인하고
infra/postgres/cdc/10-board-posts-publication.sql을 실행한다. 이 script는 delete event에서도 tenant/org/security metadata가 남도록REPLICA IDENTITY FULL을 설정한다. wal2jsonoutput plugin을 source PostgreSQL library에 설치한다. listener는 production에서wal2json만 허용한다.test_decoding은 diagnostics 전용이다.- dedicated
rag_cdcrole에LOGIN REPLICATION과 source tableSELECT권한을 최소로 부여하고CDC_SOURCE_DATABASE_URLsecret을 설정한다.
source row는 다음 canonical column 또는 alias를 제공해야 한다.
| 용도 | 허용 column 이름 |
|---|---|
| post identity | post_id, board_post_id, id |
| tenancy | tenant_id, organization_id 또는 owning_org_id |
| content | title 또는 subject, content 또는 body |
| author | author_id/creator_id/registrant_id, author_name, department_code |
| ACL | security_level, classification |
| version/time | version, updated_at, registered_at, created_at |
서로 다른 portal schema는 source DB에 narrow projection view를 만들고 CDC_BOARD_SCHEMA, CDC_BOARD_TABLE로 해당 view/table contract를 지정할 수 있다.
On-prem Compose 실행
set -a; source .env.offline; set +a
docker compose -f docker-compose.offline.yml --profile cdc up -dcdc profile은 embedding-api를 함께 활성화한다. CDC listener는 source URL과 RagService target URL을 구분해 사용한다. source password, target app password, Directory key는 deployment secret store에만 보관하며 dashboard/manifest에 포함하지 않는다.
Event 처리
| Event | 동작 | 정합성 보장 |
|---|---|---|
INSERT | trusted BoardPost metadata → title/body semantic chunk → bounded async BGE-M3 embedding → target COPY/upsert | target transaction 이후 LSN advance |
UPDATE | source version/checksum replacement → prior registry parent delete → ON DELETE CASCADE child vector cleanup → fresh COPY | lifecycle event와 replacement는 하나의 target transaction |
DELETE | delete event의 full old row metadata로 source_document_id를 계산 → parent registry hard delete | FK cascade로 모든 tb_doc_chunk_vector 제거 |
| target/embedding error | slot acknowledge 하지 않음 | 동일 source transaction 재시도 |
OfflineRagIngestor는 checksum 또는 source document identity가 바뀌면 target registry parent를 먼저 제거한다. 따라서 stale vector를 independently delete하는 별도 SQL path를 만들지 않는다.
테스트와 운영 제한
tests/test_cdc.py는 wal2json INSERT/UPDATE/DELETE parse, trusted board metadata, source LSN이 모든 downstream event 성공 뒤에만 advance되는 동작을 검증한다. 실제 source database에서의 wal2json plugin ABI, PostgreSQL parameter group, replication network ACL, WAL lag threshold는 사내 staging DB에서 smoke test해야 한다.