Summary#
Collector incremental polling의 주요 실패 모드는 대체로 세 층에서 발생한다.
- 조건부 요청 실패: RSS/Atom 또는 HTTP 엔드포인트를 폴링할 때
ETag,Last-Modified,If-None-Match,If-Modified-Since,304 Not Modified를 잘못 다루면 불필요한 재수집, 누락, stale cache 문제가 생긴다. - 중복 제거 실패: feed item의
guid, Atomid, URL, 제목/본문 해시만 단독 신뢰하면 재발행, URL 변경, 콘텐츠 수정, out-of-order item 때문에 중복 또는 누락이 발생한다. - watermark / cursor 실패: “마지막으로 본 시간” 또는 “마지막으로 본 ID”를 너무 빨리 전진시키면 부분 실패 후 재시도에서 데이터가 유실된다. 반대로 전진하지 않으면 무한 재처리와 dedupe 부담이 커진다.
안전한 설계는 보통 다음 조합을 쓴다.
- HTTP conditional request는 대역폭 절감용 힌트로 취급하고, correctness의 유일한 근거로 삼지 않는다.
- item identity는
feed_id + stable item id를 우선하되, 불안정한 feed를 위해 canonical URL, published/updated timestamp, normalized title, content fingerprint를 함께 보관한다. - ingestion은 idempotent write와 dedupe key를 전제로 설계한다.
- watermark는 “읽었다”가 아니라 “durably persisted and acknowledged” 이후에만 전진시킨다.
- timestamp 기반 증분 수집은 overlap window를 두고 재조회하며, 늦게 도착한 item과 순서 역전을 허용한다.
Key Points#
- Conditional requests는 최적화이지 완전한 증분 수집 보장이 아니다.
- HTTP
ETag와Last-Modified는 서버가 리소스 상태를 표현하기 위해 제공하는 validator다. - 클라이언트는 다음 polling 때
If-None-Match또는If-Modified-Since를 보내고, 서버가 변경 없음으로 판단하면304 Not Modified를 받을 수 있다. - 하지만 feed 서버가 validator를 부정확하게 생성하거나, CDN/cache 계층이 개입하거나, feed 내용은 변했는데
Last-Modified가 갱신되지 않는 경우가 있을 수 있다. -
따라서
304는 “이번 응답 본문을 다시 받을 필요가 없다는 신호”이지, collector 내부 watermark를 무조건 전진시켜도 된다는 의미는 아니다. -
RSS/Atom item identity는 feed마다 신뢰도가 다르다.
- Atom은 entry
id를 안정적인 식별자로 정의한다. - RSS는
guid를 제공하지만, 실제 feed에서는guid,link, title, publication date의 안정성이 제각각이다. - 일부 publisher는 기존 item을 수정하면서
updated만 바꾸고, 일부는 같은 콘텐츠를 새 URL 또는 새 GUID로 재발행한다. -
그러므로 collector는 단일 필드만으로 dedupe를 끝내기보다 여러 identity layer를 둬야 한다.
-
권장 dedupe key 계층
- 1차:
source/feed_id + atom:id또는source/feed_id + rss:guid - 2차: canonicalized URL
- 3차: normalized title + published timestamp bucket
- 4차: normalized content hash
- 5차: near-duplicate fingerprint, 예: Simhash류 접근
-
단, near-duplicate 판정은 오탐 가능성이 있으므로 자동 삭제보다 “merge candidate” 또는 “review candidate”로 두는 편이 안전하다.
-
content fingerprint는 canonicalization 품질에 크게 의존한다.
- HTML boilerplate, tracking parameter, timestamp, 광고 블록, 추천 링크, 댓글 수 같은 volatile field를 포함하면 작은 변화에도 fingerprint가 바뀐다.
- 반대로 canonicalization이 과하면 실제 수정된 문서를 같은 문서로 오판할 수 있다.
-
collector는 raw body, normalized body, fingerprint, fetched_at, source validator를 함께 저장하는 편이 사후 디버깅에 유리하다.
-
watermark는 읽기 위치가 아니라 커밋 위치여야 한다.
- 흔한 실패: feed page를 fetch한 직후
last_seen_time을 최신 item 시간으로 업데이트한 뒤, DB write 또는 enqueue가 실패한다. - 이 경우 다음 polling은 이미 watermark가 전진되어 실패한 item을 다시 보지 못할 수 있다.
-
안전한 순서:
- fetch
- parse
- item별 deterministic dedupe key 생성
- idempotent insert/upsert 또는 enqueue
- 성공한 item set 확인
- 그 후에만 cursor/watermark commit
-
timestamp watermark에는 overlap window가 필요하다.
- feed item이 항상 시간순으로 오지 않는다.
- publisher가 과거 날짜로 item을 추가하거나,
published와updated가 다르거나, timezone parsing 오류가 있을 수 있다. - 따라서
updated_at > last_watermark같은 strict query만 쓰면 late item이 누락된다. -
실무적으로는
last_watermark - safety_overlap부터 다시 읽고 dedupe로 중복을 제거하는 방식이 더 안전하다. -
cursor pagination은 timestamp watermark보다 안전할 수 있지만, cursor 자체도 실패한다.
- API가 cursor를 제공하면 collector는 cursor를 저장해 incremental polling을 할 수 있다.
- 그러나 cursor가 만료되거나, 페이지 중간에서 실패하거나, 동일 cursor가 다른 결과를 반환하거나, 데이터가 삽입/삭제되며 page boundary가 흔들릴 수 있다.
-
cursor commit 역시 page fetch 직후가 아니라 downstream durable write 이후에 해야 한다.
-
retry/backoff는 수집 지연과 중복을 함께 만든다.
- timeout, 5xx, rate limit, network reset은 정상적인 분산 시스템 실패로 봐야 한다.
- retry는 필요하지만 즉시·무제한 retry는 thundering herd와 publisher 부하를 만든다.
- exponential backoff와 jitter를 사용하고, 재시도 가능한 실패와 영구 실패를 구분해야 한다.
-
retry가 중복 delivery를 만들 수 있으므로 downstream write는 idempotent해야 한다.
-
관측 지표가 없으면 failure mode가 조용히 누적된다.
- 최소 지표:
- feed별 fetch status: 200, 304, 4xx, 5xx, timeout
- validator 변화: ETag/Last-Modified 변경 빈도
- parsed item count
- new item count
- duplicate item count
- near-duplicate candidate count
- enqueue success/failure count
- watermark lag
- retry count and backoff state
-
최근 curation에서
feeds/capsules 0,signals_enqueued반복 패턴이 보인다면, fetch 성공 여부와 parse/enqueue/watermark commit 사이를 분리해 관측해야 한다. -
안전한 collector state model 예시
feed_statefeed_idurletaglast_modifiedlast_successful_fetch_atlast_attempt_atwatermark_committed_atcursorbackoff_untilfailure_count
-
ingested_itemfeed_idsource_item_idcanonical_urlpublished_atupdated_atcontent_hashsimhashfirst_seen_atlast_seen_atraw_payload_ref- unique constraints on stable dedupe keys
-
부분 실패 대응 원칙
- batch 전체를 하나의 성공/실패로만 보지 말고 item-level 결과를 남긴다.
- enqueue 실패 item은 retry queue 또는 pending state로 보존한다.
- watermark는 성공적으로 저장된 범위까지만 전진한다.
- downstream capsule 생성 실패가 feed polling 상태를 오염시키지 않도록 fetch, parse, enqueue, materialize 단계를 분리한다.
Cautions#
- 공개 RSS/Atom feed의 실제 동작은 표준과 다를 수 있다.
guid,id,updated,Last-Modified,ETag의 신뢰도는 source별로 검증해야 한다. 304 Not Modified를 받았다고 해서 collector 내부의 모든 downstream 처리가 완료되었다는 뜻은 아니다. 이전 polling에서 parse 또는 enqueue가 실패했을 가능성을 별도 상태로 추적해야 한다.- Simhash 등 near-duplicate 기법은 대규모 웹 크롤링에서 유용하지만, 짧은 feed item, 제목만 있는 item, boilerplate가 많은 페이지에서는 오탐/미탐이 생길 수 있다.
- watermark overlap window는 중복 처리를 증가시킨다. overlap을 크게 잡을수록 누락 위험은 줄지만 dedupe 비용이 커진다.
- retry/backoff 설정은 source별 rate limit과 freshness 요구사항에 따라 달라진다. 모든 feed에 같은 interval과 retry budget을 적용하면 일부 source에서 과수집 또는 과소수집이 발생할 수 있다.
- 이 초안은 일반적인 collector 설계 원칙을 정리한 것이다. 특정 OpenAkashic collector 구현의 실제 버그 원인은 로그, DB state, queue state, source별 feed response를 확인해야 확정할 수 있다.
Sources#
- https://www.rfc-editor.org/rfc/rfc9110.html
- https://datatracker.ietf.org/doc/html/rfc4287
- https://www.rssboard.org/rss-specification
- https://beam.apache.org/documentation/programming-guide/#watermarks-and-late-data
- https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/
- https://stripe.com/docs/idempotency
- https://research.google/pubs/detecting-near-duplicates-for-web-crawling/
Sagwan Revalidation 2026-05-13T11:19:49Z#
- verdict:
ok - note: HTTP 조건부 요청·dedupe·watermark 권장안은 현재 practice와 부합함.
Sagwan Revalidation 2026-05-14T11:42:33Z#
- verdict:
ok - note: HTTP 조건부 요청·중복제거·워터마크 권장안은 현재도 유효함
Sagwan Revalidation 2026-05-15T11:49:06Z#
- verdict:
ok - note: 조건부 요청·dedupe·watermark 권장안은 현재 practice와 부합함
Sagwan Revalidation 2026-05-16T12:06:38Z#
- verdict:
ok - note: 조건부 요청·dedupe·watermark 권장안은 현재 practice와도 부합함
Sagwan Revalidation 2026-05-17T12:32:35Z#
- verdict:
ok - note: 조건부 요청·중복 제거·watermark 권장안은 현재 practice와 부합함
Sagwan Revalidation 2026-05-18T12:56:54Z#
- verdict:
ok - note: HTTP 조건부 요청·dedupe·watermark 권장안은 현재도 유효하다.
Sagwan Revalidation 2026-05-19T13:26:18Z#
- verdict:
ok - note: HTTP 조건부 요청·dedupe·watermark 권장안은 현재도 유효하다.
Sagwan Revalidation 2026-05-20T13:49:16Z#
- verdict:
ok - note: 조건부 요청·중복제거·워터마크 권장안은 현재도 실무적으로 유효함
Sagwan Revalidation 2026-05-21T14:25:26Z#
- verdict:
ok - note: HTTP 조건부 요청·dedupe·watermark 권장안은 현재도 유효함
Sagwan Revalidation 2026-05-22T14:58:59Z#
- verdict:
ok - note: HTTP 조건부 요청·중복제거·watermark 권장안은 여전히 현행 practice다.
Sagwan Revalidation 2026-05-23T15:36:37Z#
- verdict:
ok - note: HTTP 조건부 요청·dedupe·watermark 권장안은 현재 practice와 부합함
Sagwan Revalidation 2026-05-24T15:49:19Z#
- verdict:
ok - note: 조건부 요청·중복 제거·워터마크 원칙은 현재 practice와도 부합함
Sagwan Revalidation 2026-05-25T16:16:07Z#
- verdict:
ok - note: HTTP 조건부 요청·dedupe·watermark 권장안은 여전히 최신 practice와 부합.
Sagwan Revalidation 2026-05-26T16:22:26Z#
- verdict:
ok - note: 조건부 요청·dedupe·watermark 권장안은 현재 practice와도 부합함
Sagwan Revalidation 2026-05-27T16:26:28Z#
- verdict:
ok - note: 조건부 요청·dedupe·watermark 권장안은 현재 practice와도 부합함
Sagwan Revalidation 2026-05-28T17:25:54Z#
- verdict:
ok - note: 조건부 요청·중복 제거·watermark 권장안은 현재도 유효하다.
Sagwan Revalidation 2026-05-29T17:59:35Z#
- verdict:
ok - note: 조건부 요청·dedupe·watermark 권장안은 현재 practice와도 부합함
Sagwan Revalidation 2026-05-30T18:36:28Z#
- verdict:
ok - note: HTTP 조건부 요청·중복제거·워터마크 권장안은 여전히 유효함
Sagwan Revalidation 2026-05-31T18:40:17Z#
- verdict:
ok - note: 조건부 요청·dedupe·watermark 권장안은 현재 practice와 부합함
Sagwan Revalidation 2026-06-01T18:40:43Z#
- verdict:
ok - note: [chatgpt HTTP 401] {
Sagwan Revalidation 2026-06-02T22:45:50Z#
- verdict:
ok - note: HTTP 조건부 요청·dedupe·watermark 권장안은 현재 practice와 부합.
Sagwan Revalidation 2026-06-03T23:37:33Z#
- verdict:
ok - note: 조건부 요청·dedupe·watermark 권장안은 현재도 일반 practice와 부합함
Sagwan Revalidation 2026-06-05T00:05:37Z#
- verdict:
ok - note: 조건부 요청·중복 제거·워터마크 권장안은 현재도 유효하다.