[Bug]: Replication result depends on whether the target has a validate_doc_update function
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 44/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- erlang, javascript
- Lĩnh vực
- database, databases, distributed-systems
Hướng nghiên cứu
Start with couch_db:before_docs_update and prep_and_validate_replicated_updates, then trace how couch_replicator_worker:find_missing handles the missing ratio. Run the provided curl and jq reproduction against CouchDB 3.5.3 and compare the final document in t1 and t2. Done means both targets reach the same document state with and without the accepting validate_doc_update design doc.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Version
3.5.3
Describe the problem you're encountering
Two target databases that get the same replications, in the same order, from the same sources can end up with a different state for a document: one ends deleted, the other ends live with an old revision as the winner. The only difference between the targets is a design doc whose validate_doc_update accepts everything.
It shows up when a target first receives a revision with a short history (from a replica with a low revs_limit) and later receives the same revision again with its full history.
Expected Behaviour
I would expect replication to give the same result whether or not the target has a validate_doc_update function that accepts the document.
Steps to Reproduce
Needs curl and jq. Single node, one-shot _replicate, run in order.
COUCH=http://adm:[email protected]:5984
J='Content-Type: application/json'
for db in a c b d t1 t2; do curl -sS -X PUT "$COUCH/$db" > /dev/null; done
curl -sS -X PUT "$COUCH/b/_revs_limit" -d 1 > /dev/null
curl -sS -X PUT "$COUCH/d/_revs_limit" -d 2 > /dev/null
curl -sS -X PUT "$COUCH/t2/_design/accept" -H "$J" \
-d '{"validate_doc_update":"function(newDoc, oldDoc, userCtx, secObj) {}"}' > /dev/null
rep() { curl -sS -X POST "$COUCH/_replicate" -H "$J" \
-d "{\"source\":\"$COUCH/$1\",\"target\":\"$COUCH/$2\"${3:+,$3}}" > /dev/null; }
ONLY_X='"doc_ids":["X"]'
# create X (1-a) on a, replicate to c
REV=$(curl -sS -X PUT "$COUCH/a/X" -H "$J" -d '{"v":"a"}' | jq -r .rev)
rep a c "$ONLY_X"
# 6 unrelated docs on a
curl -sS -X POST "$COUCH/a/_bulk_docs" -H "$J" -d '{"docs":[
{"_id":"f1"},{"_id":"f2"},{"_id":"f3"},{"_id":"f4"},{"_id":"f5"},{"_id":"f6"}]}' > /dev/null
# edit X (2-b) on a, replicate to b (revs_limit 1, so b keeps 2-b with no ancestors)
REV=$(curl -sS -X PUT "$COUCH/a/X" -H "$J" -d "{\"_rev\":\"$REV\",\"v\":\"b\"}" | jq -r .rev)
rep a b "$ONLY_X"
# both targets: c then b, giving two separate roots 1-a and 2-b
for t in t1 t2; do rep c $t; rep b $t; done
# both targets: replicate a with one worker, batch size 1
for t in t1 t2; do rep a $t '"worker_processes":1,"worker_batch_size":1'; done
# delete X (3-d) on a, replicate to d (revs_limit 2), then d to both targets
curl -sS -X DELETE "$COUCH/a/X?rev=$REV" > /dev/null
rep a d "$ONLY_X"
for t in t1 t2; do rep d $t; done
curl -sS "$COUCH/t1/X"
curl -sS "$COUCH/t2/X"
Output on 3.5.3:
{"error":"not_found","reason":"deleted"}
{"_id":"X","_rev":"1-cd6dcd82d939d5b6220025fbc573b36a","v":"a"}
Your Environment
CouchDB 3.5.3 (git 7a1f97558), Erlang/OTP 28, single node, q=1 n=1, macOS arm64.
Additional Context
From reading the source, I think two things interact:
couch_db:before_docs_updateonly runsprep_and_validate_replicated_updateswhen the db has a VDU (or a design doc or attachments in the request). That step drops a replicated revision that is already a leaf; without a VDU the same path gets merged.couch_replicator_worker:find_missingskips_revs_diffonce the missing ratio average goes over 0.95 (6 batches in a row where everything was missing), and then re-sends revisions the target already has, with the longer history.
The same split happens with default replication settings when 20,000 unrelated docs come before X in a's changes. If the unrelated docs come after X, or there are only 5, both targets end the same. The relevant files look unchanged on main.
Fuller repro with all runs and controls: https://github.com/blackwell-systems/normalization-confluence/tree/main/research/couchdb-replicator
- Ngôn ngữ chính
- Erlang
- Star
- 7k
- Fork
- 1.1k
- Merge trung bình
- 10 giờ 16 phút
- Pull request đã merge (30 ngày)
- 35
Chuẩn bị môi trường
Khởi chạy dev container của dự án ngay trên trình duyệt, bằng tài khoản GitHub của bạn.
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của apache/couchdb
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 45/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Fix: Warning: 'catch ...' is deprecated; please use 'try ... catch ... end' insteadCó thể làm lại được @devx-arjun đã nhận 9 ngày trước và không có pull request nào đang mở. Đang mởbeginner-friendly build chore patches-welcome
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 45/100
apache/couchdb#6144 · 4 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug needs-triage
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 48/100
apache/couchdb#6132 · 3 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[ENHANCEMENT]: Add seq checkpoints to continuous feedsCó thể đã có người làm @nickva đã nhận 2 ngày trước. Đang mởenhancement
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 45/100
apache/couchdb#6120 · 7 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
enhancement needs-triage
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 55/100
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của apache/couchdb
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
tursodatabase/turso#10002 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
mariadb-operator/mariadb-operator#1962 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
arabold/docs-mcp-server#548 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug difficulty: easy
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
MetroLogic/fluxapay_contract#1022 ·
Maintainer thường phản hồi trong vòng 1 ngày