Concurrency-Safe Resource Backend for a Collection Framework수집 프레임워크를 위한 동시성 안전 리소스 백엔드
A shared service layer for collector accounts, seeds, sessions, and captures.수집기의 계정·시드·세션·캡처를 위한 공용 서비스 레이어.
Problem문제
Collectors operating across hundreds of login-gated sources kept getting blocked when concurrent runs reused the same account. Seed scheduling, session merging, and capture handoff were also duplicated across individual collectors.수백 개의 로그인 필수 소스를 도는 수집기들이 동시 실행에서 같은 계정을 재사용하다 차단당하고 있었습니다. 시드 스케줄링, 세션 병합, 캡처 전달도 수집기마다 중복 구현되어 있었습니다.
System시스템
Primary maintainer for a FastAPI backend with 8 routers and 32 v2 endpoints across a MongoDB and PostgreSQL dual stack. Atomic account acquire/release prevents shared-account abuse, seed scheduling assigns boards dynamically per request, Playwright StorageState sessions are merged automatically, and a Site Domain Management module rewrites URLs as source sites change domains.MongoDB·PostgreSQL 듀얼 스택에서 8개 라우터, 32개 v2 엔드포인트를 가진 FastAPI 백엔드의 주 메인테이너. 원자적 계정 획득/반환으로 공유 계정 남용을 막고, 시드 스케줄링은 요청마다 게시판을 동적으로 배분하며, Playwright StorageState 세션은 자동으로 병합되고, Site Domain Management 모듈이 소스 사이트의 도메인 변경에 맞춰 URL을 재작성합니다.
Impact임팩트
Every collector now goes through one backend for resources, so blocking-avoidance and concurrency policy live in one place. I led the MongoDB to PostgreSQL migration for relational paths and a v3.0.0 architecture refresh that retired the legacy API surface.이제 모든 수집기가 하나의 백엔드를 통해 리소스를 받으므로 차단 회피와 동시성 정책이 한곳에 모입니다. 관계형 경로의 MongoDB → PostgreSQL 마이그레이션과 레거시 API를 정리한 v3.0.0 아키텍처 리프레시를 주도했습니다.
Architecture notes아키텍처 노트
The public lab uses the same operating pattern shown here: a scheduled agent does the heavy work ahead of time, writes a static JSON artifact, and the page reads that artifact. Loading the page never calls an LLM. If collection or generation fails, the existing page still works; only the next refresh is delayed.
공개 Lab도 여기서 보여준 것과 같은 운영 패턴으로 동작합니다. 스케줄 에이전트가 무거운 작업을 미리 처리해 정적 JSON 아티팩트를 쓰고, 페이지는 그 파일을 읽기만 합니다. 페이지를 여는 것만으로는 LLM이 호출되지 않으며, 수집이나 생성이 실패해도 기존 페이지는 계속 동작하고 다음 갱신만 늦어집니다.
The backend’s central abstraction is “resources”: accounts, seeds (board entries), and Playwright sessions. A collector requests resources, runs, and releases them. Behind the API, atomic MongoDB updates implement acquire/release with a state machine (ACTIVE → USING → INACTIVE / BLOCKED). If active resources are exhausted, the API can reclaim “zombie USING” rows whose owning job died, preventing starvation.
Session merge is a small but important detail: when a new Playwright StorageState is uploaded, the backend merges its cookies and origins with the existing cached session. Duplicates collapse to the newer value, and non-overlapping entries are preserved. This avoids losing cookies that may only be set during the initial login flow.
The MongoDB to PostgreSQL migration moved strongly relational data, such as site metadata, domain rewrites, and capture audit records, to PostgreSQL via Tortoise ORM. Account and session pools stayed on MongoDB, where atomic single-document updates fit naturally.
백엔드의 중심 추상화는 "리소스"입니다: 계정, 시드(게시판 엔트리), Playwright 세션. 수집기는 리소스를 요청하고, 실행하고, 반환합니다. API 뒤에서는 원자적 MongoDB 업데이트가 상태 머신(ACTIVE → USING → INACTIVE / BLOCKED)으로 획득/반환을 구현합니다. 활성 리소스가 소진되면 소유 잡이 죽어버린 "좀비 USING" 행을 회수해 기아 상태를 방지합니다.
세션 병합은 작지만 중요한 디테일입니다. 새 Playwright StorageState가 업로드되면 백엔드가 그 쿠키와 오리진을 기존 캐시 세션과 병합합니다. 중복은 더 새로운 값으로 수렴하고, 겹치지 않는 항목은 보존됩니다. 최초 로그인 플로우에서만 설정되는 쿠키를 잃지 않기 위한 장치입니다.
MongoDB → PostgreSQL 마이그레이션은 사이트 메타데이터, 도메인 재작성, 캡처 감사 기록처럼 관계형 성격이 강한 데이터를 Tortoise ORM 기반 PostgreSQL로 옮겼습니다. 계정·세션 풀은 원자적 단일 문서 업데이트가 자연스러운 MongoDB에 남겼습니다.