Fix COUCHDB-1363 - race condition in couch_changes It's necessary to re-open the #db after subscribing to notifications so that updates are not lost. In practice, this is rarely problematic because the next change will cause everything to catch up, but if a quick burst of changes happens while replication is starting the replication can go stale. Detected by intermittent replicator_db js test failures.
Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/6a04e333 Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/6a04e333 Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/6a04e333 Branch: refs/heads/1.1.x Commit: 6a04e333663596aba4a4d8889e63459b95ef99ff Parents: c9b20f2 Author: Randall Leeds <[email protected]> Authored: Wed Dec 14 20:12:08 2011 -0800 Committer: Randall Leeds <[email protected]> Committed: Thu Dec 15 16:53:28 2011 -0800 ---------------------------------------------------------------------- src/couchdb/couch_changes.erl | 18 ++++++++++++------ 1 files changed, 12 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb/blob/6a04e333/src/couchdb/couch_changes.erl ---------------------------------------------------------------------- diff --git a/src/couchdb/couch_changes.erl b/src/couchdb/couch_changes.erl index 2be3779..b89f4d2 100644 --- a/src/couchdb/couch_changes.erl +++ b/src/couchdb/couch_changes.erl @@ -20,23 +20,28 @@ handle_changes(#changes_args{style=Style}=Args1, Req, Db) -> #changes_args{feed = Feed} = Args = Args1#changes_args{ filter = make_filter_fun(Args1#changes_args.filter, Style, Req, Db) }, - StartSeq = case Args#changes_args.dir of - rev -> - couch_db:get_update_seq(Db); - fwd -> - Args#changes_args.since + Start = fun() -> + {ok, Db} = couch_db:reopen(Db0), + StartSeq = case Dir of + rev -> + couch_db:get_update_seq(Db); + fwd -> + Since + end, + {Db, StartSeq} end, if Feed == "continuous" orelse Feed == "longpoll" -> fun(CallbackAcc) -> {Callback, UserAcc} = get_callback_acc(CallbackAcc), Self = self(), {ok, Notify} = couch_db_update_notifier:start_link( - fun({_, DbName}) when DbName == Db#db.name -> + fun({_, DbName}) when Db0#db.name == DbName -> Self ! db_updated; (_) -> ok end ), + {Db, StartSeq} = Start(), UserAcc2 = start_sending_changes(Callback, UserAcc, Feed), {Timeout, TimeoutFun} = get_changes_timeout(Args, Callback), try @@ -58,6 +63,7 @@ handle_changes(#changes_args{style=Style}=Args1, Req, Db) -> true -> fun(CallbackAcc) -> {Callback, UserAcc} = get_callback_acc(CallbackAcc), + {Db, StartSeq} = Start(), UserAcc2 = start_sending_changes(Callback, UserAcc, Feed), {ok, {_, LastSeq, _Prepend, _, _, UserAcc3, _, _, _, _}} = send_changes(
