You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by da...@apache.org on 2017/07/20 19:05:24 UTC

[couchdb] 11/26: FIXUP: Reuse fabric lookup results

This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch optimize-ddoc-cache
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 45cf36c11ecb3f301df74181b3502576df7ff1ad
Author: Paul J. Davis <pa...@gmail.com>
AuthorDate: Thu Jul 6 13:48:15 2017 -0500

    FIXUP: Reuse fabric lookup results
    
    On suggestion from @chewbranca I've gone ahead and made the optimization
    to insert the revid or non-revid specific version of the request design
    document.
---
 src/ddoc_cache/src/ddoc_cache_entry.erl            | 33 +++++++++++++++---
 src/ddoc_cache/src/ddoc_cache_entry_custom.erl     |  7 +++-
 src/ddoc_cache/src/ddoc_cache_entry_ddocid.erl     | 13 +++++++-
 src/ddoc_cache/src/ddoc_cache_entry_ddocid_rev.erl | 12 ++++++-
 .../src/ddoc_cache_entry_validation_funs.erl       |  7 +++-
 src/ddoc_cache/src/ddoc_cache_lru.erl              | 30 ++++++++++++-----
 src/ddoc_cache/test/ddoc_cache_basic_test.erl      | 39 +++++++++++++++++-----
 src/ddoc_cache/test/ddoc_cache_entry_test.erl      |  6 ++--
 src/ddoc_cache/test/ddoc_cache_eviction_test.erl   |  6 ++--
 src/ddoc_cache/test/ddoc_cache_no_cache_test.erl   |  1 +
 src/ddoc_cache/test/ddoc_cache_open_error_test.erl |  2 +-
 src/ddoc_cache/test/ddoc_cache_refresh_test.erl    | 17 +++++++---
 src/ddoc_cache/test/ddoc_cache_remove_test.erl     | 30 +++++++++++++----
 13 files changed, 161 insertions(+), 42 deletions(-)

diff --git a/src/ddoc_cache/src/ddoc_cache_entry.erl b/src/ddoc_cache/src/ddoc_cache_entry.erl
index 914e32e..79c3dcf 100644
--- a/src/ddoc_cache/src/ddoc_cache_entry.erl
+++ b/src/ddoc_cache/src/ddoc_cache_entry.erl
@@ -18,8 +18,9 @@
     dbname/1,
     ddocid/1,
     recover/1,
+    insert/2,
 
-    start_link/1,
+    start_link/2,
     shutdown/1,
     open/2,
     accessed/1,
@@ -65,8 +66,12 @@ recover({Mod, Arg}) ->
     Mod:recover(Arg).
 
 
-start_link(Key) ->
-    Pid = proc_lib:spawn_link(?MODULE, init, [Key]),
+insert({Mod, Arg}, Value) ->
+    Mod:insert(Arg, Value).
+
+
+start_link(Key, Default) ->
+    Pid = proc_lib:spawn_link(?MODULE, init, [{Key, Default}]),
     {ok, Pid}.
 
 
@@ -99,7 +104,7 @@ refresh(Pid) ->
     gen_server:cast(Pid, force_refresh).
 
 
-init(Key) ->
+init({Key, undefined}) ->
     true = ets:update_element(?CACHE, Key, {#entry.pid, self()}),
     St = #st{
         key = Key,
@@ -108,6 +113,26 @@ init(Key) ->
         accessed = 1
     },
     ?EVENT(started, Key),
+    gen_server:enter_loop(?MODULE, [], St);
+
+init({Key, Default}) ->
+    Updates = [
+        {#entry.val, Default},
+        {#entry.pid, self()}
+    ],
+    NewTs = os:timestamp(),
+    true = ets:update_element(?CACHE, Key, Updates),
+    true = ets:insert(?LRU, {{NewTs, Key, self()}}),
+    Msg = {'$gen_cast', refresh},
+    St = #st{
+        key = Key,
+        val = {open_ok, {ok, Default}},
+        opener = erlang:send_after(?REFRESH_TIMEOUT, self(), Msg),
+        waiters = undefined,
+        ts = NewTs,
+        accessed = 1
+    },
+    ?EVENT(default_started, Key),
     gen_server:enter_loop(?MODULE, [], St).
 
 
diff --git a/src/ddoc_cache/src/ddoc_cache_entry_custom.erl b/src/ddoc_cache/src/ddoc_cache_entry_custom.erl
index d858ad6..9eaf16f 100644
--- a/src/ddoc_cache/src/ddoc_cache_entry_custom.erl
+++ b/src/ddoc_cache/src/ddoc_cache_entry_custom.erl
@@ -16,7 +16,8 @@
 -export([
     dbname/1,
     ddocid/1,
-    recover/1
+    recover/1,
+    insert/2
 ]).
 
 
@@ -30,3 +31,7 @@ ddocid(_) ->
 
 recover({DbName, Mod}) ->
     Mod:recover(DbName).
+
+
+insert(_, _) ->
+    ok.
diff --git a/src/ddoc_cache/src/ddoc_cache_entry_ddocid.erl b/src/ddoc_cache/src/ddoc_cache_entry_ddocid.erl
index cac9abc..5248469 100644
--- a/src/ddoc_cache/src/ddoc_cache_entry_ddocid.erl
+++ b/src/ddoc_cache/src/ddoc_cache_entry_ddocid.erl
@@ -16,7 +16,8 @@
 -export([
     dbname/1,
     ddocid/1,
-    recover/1
+    recover/1,
+    insert/2
 ]).
 
 
@@ -33,3 +34,13 @@ ddocid({_, DDocId}) ->
 
 recover({DbName, DDocId}) ->
     fabric:open_doc(DbName, DDocId, [ejson_body, ?ADMIN_CTX]).
+
+
+insert({DbName, DDocId}, {ok, #doc{revs = Revs} = DDoc}) ->
+    {Depth, [RevId | _]} = Revs,
+    Rev = {Depth, RevId},
+    Key = {ddoc_cache_entry_ddocid_rev, {DbName, DDocId, Rev}},
+    spawn(fun() -> ddoc_cache_lru:insert(Key, DDoc) end);
+
+insert(_, _) ->
+    ok.
diff --git a/src/ddoc_cache/src/ddoc_cache_entry_ddocid_rev.erl b/src/ddoc_cache/src/ddoc_cache_entry_ddocid_rev.erl
index 012abab..868fa77 100644
--- a/src/ddoc_cache/src/ddoc_cache_entry_ddocid_rev.erl
+++ b/src/ddoc_cache/src/ddoc_cache_entry_ddocid_rev.erl
@@ -16,7 +16,8 @@
 -export([
     dbname/1,
     ddocid/1,
-    recover/1
+    recover/1,
+    insert/2
 ]).
 
 
@@ -35,3 +36,12 @@ recover({DbName, DDocId, Rev}) ->
     Opts = [ejson_body, ?ADMIN_CTX],
     {ok, [Resp]} = fabric:open_revs(DbName, DDocId, [Rev], Opts),
     Resp.
+
+
+insert({DbName, DDocId, _Rev}, {ok, #doc{} = DDoc}) ->
+    Key = {ddoc_cache_entry_ddocid, {DbName, DDocId}},
+    spawn(fun() -> ddoc_cache_lru:insert(Key, DDoc) end);
+
+insert(_, _) ->
+    ok.
+
diff --git a/src/ddoc_cache/src/ddoc_cache_entry_validation_funs.erl b/src/ddoc_cache/src/ddoc_cache_entry_validation_funs.erl
index 3d43f7a..2182dea 100644
--- a/src/ddoc_cache/src/ddoc_cache_entry_validation_funs.erl
+++ b/src/ddoc_cache/src/ddoc_cache_entry_validation_funs.erl
@@ -16,7 +16,8 @@
 -export([
     dbname/1,
     ddocid/1,
-    recover/1
+    recover/1,
+    insert/2
 ]).
 
 
@@ -37,3 +38,7 @@ recover(DbName) ->
         end
     end, DDocs),
     {ok, Funs}.
+
+
+insert(_, _) ->
+    ok.
diff --git a/src/ddoc_cache/src/ddoc_cache_lru.erl b/src/ddoc_cache/src/ddoc_cache_lru.erl
index cbe481e..6ae4de4 100644
--- a/src/ddoc_cache/src/ddoc_cache_lru.erl
+++ b/src/ddoc_cache/src/ddoc_cache_lru.erl
@@ -18,6 +18,7 @@
 -export([
     start_link/0,
     open/1,
+    insert/2,
     refresh/2
 ]).
 
@@ -53,9 +54,9 @@ start_link() ->
 open(Key) ->
     try ets:lookup(?CACHE, Key) of
         [] ->
-            lru_start(Key);
+            lru_start(Key, true);
         [#entry{pid = undefined}] ->
-            lru_start(Key);
+            lru_start(Key, false);
         [#entry{val = undefined, pid = Pid}] ->
             couch_stats:increment_counter([ddoc_cache, miss]),
             ddoc_cache_entry:open(Pid, Key);
@@ -69,6 +70,15 @@ open(Key) ->
     end.
 
 
+insert(Key, Value) ->
+    case ets:lookup(?CACHE, Key) of
+        [] ->
+            gen_server:call(?MODULE, {start, Key, Value}, infinity);
+        [#entry{}] ->
+            ok
+    end.
+
+
 refresh(DbName, DDocIds) ->
     gen_server:cast(?MODULE, {refresh, DbName, DDocIds}).
 
@@ -96,7 +106,7 @@ terminate(_Reason, St) ->
     ok.
 
 
-handle_call({start, Key}, _From, St) ->
+handle_call({start, Key, Default}, _From, St) ->
     #st{
         pids = Pids,
         dbs = Dbs,
@@ -108,7 +118,7 @@ handle_call({start, Key}, _From, St) ->
             case trim(St, CurSize, max(0, MaxSize)) of
                 {ok, N} ->
                     true = ets:insert_new(?CACHE, #entry{key = Key}),
-                    {ok, Pid} = ddoc_cache_entry:start_link(Key),
+                    {ok, Pid} = ddoc_cache_entry:start_link(Key, Default),
                     true = ets:update_element(?CACHE, Key, {#entry.pid, Pid}),
                     ok = khash:put(Pids, Pid, Key),
                     store_key(Dbs, Key, Pid),
@@ -167,7 +177,7 @@ handle_cast({do_refresh, DbName, DDocIdList}, St) ->
             lists:foreach(fun(DDocId) ->
                 case khash:lookup(DDocIds, DDocId) of
                     {value, Keys} ->
-                        khash:fold(Keys, fun(_, Pid, _) ->
+                        khash:fold(Keys, fun(Key, Pid, _) ->
                             ddoc_cache_entry:refresh(Pid)
                         end, nil);
                     not_found ->
@@ -222,11 +232,15 @@ handle_db_event(_DbName, _Event, St) ->
     {ok, St}.
 
 
-lru_start(Key) ->
-    case gen_server:call(?MODULE, {start, Key}, infinity) of
+lru_start(Key, DoInsert) ->
+    case gen_server:call(?MODULE, {start, Key, undefined}, infinity) of
         {ok, Pid} ->
             couch_stats:increment_counter([ddoc_cache, miss]),
-            ddoc_cache_entry:open(Pid, Key);
+            Resp = ddoc_cache_entry:open(Pid, Key),
+            if not DoInsert -> ok; true ->
+                ddoc_cache_entry:insert(Key, Resp)
+            end,
+            Resp;
         full ->
             couch_stats:increment_counter([ddoc_cache, recovery]),
             ddoc_cache_entry:recover(Key)
diff --git a/src/ddoc_cache/test/ddoc_cache_basic_test.erl b/src/ddoc_cache/test/ddoc_cache_basic_test.erl
index f908c78..7f6dbc9 100644
--- a/src/ddoc_cache/test/ddoc_cache_basic_test.erl
+++ b/src/ddoc_cache/test/ddoc_cache_basic_test.erl
@@ -27,11 +27,22 @@ recover(DbName) ->
     {ok, {DbName, totes_custom}}.
 
 
+start_couch() ->
+    Ctx = ddoc_cache_tutil:start_couch(),
+    meck:new(ddoc_cache_ev, [passthrough]),
+    Ctx.
+
+
+stop_couch(Ctx) ->
+    meck:unload(),
+    ddoc_cache_tutil:stop_couch(Ctx).
+
+
 check_basic_test_() ->
     {
         setup,
-        fun ddoc_cache_tutil:start_couch/0,
-        fun ddoc_cache_tutil:stop_couch/1,
+        fun start_couch/0,
+        fun stop_couch/1,
         {with, [
             fun cache_ddoc/1,
             fun cache_ddoc_rev/1,
@@ -58,25 +69,31 @@ check_no_vdu_test_() ->
 
 cache_ddoc({DbName, _}) ->
     ddoc_cache_tutil:clear(),
+    meck:reset(ddoc_cache_ev),
     ?assertEqual(0, ets:info(?CACHE, size)),
     Resp1 = ddoc_cache:open_doc(DbName, ?FOOBAR),
     ?assertMatch({ok, #doc{id = ?FOOBAR}}, Resp1),
-    ?assertEqual(1, ets:info(?CACHE, size)),
+    meck:wait(ddoc_cache_ev, event, [started, '_'], 1000),
+    meck:wait(ddoc_cache_ev, event, [default_started, '_'], 1000),
+    ?assertEqual(2, ets:info(?CACHE, size)),
     Resp2 = ddoc_cache:open_doc(DbName, ?FOOBAR),
     ?assertEqual(Resp1, Resp2),
-    ?assertEqual(1, ets:info(?CACHE, size)).
+    ?assertEqual(2, ets:info(?CACHE, size)).
 
 
 cache_ddoc_rev({DbName, _}) ->
     ddoc_cache_tutil:clear(),
+    meck:reset(ddoc_cache_ev),
     Rev = ddoc_cache_tutil:get_rev(DbName, ?FOOBAR),
     ?assertEqual(0, ets:info(?CACHE, size)),
     Resp1 = ddoc_cache:open_doc(DbName, ?FOOBAR, Rev),
     ?assertMatch({ok, #doc{id = ?FOOBAR}}, Resp1),
-    ?assertEqual(1, ets:info(?CACHE, size)),
+    meck:wait(ddoc_cache_ev, event, [started, '_'], 1000),
+    meck:wait(ddoc_cache_ev, event, [default_started, '_'], 1000),
+    ?assertEqual(2, ets:info(?CACHE, size)),
     Resp2 = ddoc_cache:open_doc(DbName, ?FOOBAR, Rev),
     ?assertEqual(Resp1, Resp2),
-    ?assertEqual(1, ets:info(?CACHE, size)),
+    ?assertEqual(2, ets:info(?CACHE, size)),
 
     % Assert that the non-rev cache entry is separate
     Resp3 = ddoc_cache:open_doc(DbName, ?FOOBAR),
@@ -108,12 +125,16 @@ cache_custom({DbName, _}) ->
 
 cache_ddoc_refresher_unchanged({DbName, _}) ->
     ddoc_cache_tutil:clear(),
+    meck:reset(ddoc_cache_ev),
     ?assertEqual(0, ets:info(?CACHE, size)),
     ddoc_cache:open_doc(DbName, ?FOOBAR),
-    [Entry1] = ets:lookup(?CACHE, ets:first(?CACHE)),
+    meck:wait(ddoc_cache_ev, event, [started, '_'], 1000),
+    meck:wait(ddoc_cache_ev, event, [default_started, '_'], 1000),
+    Tab1 = [_, _] = lists:sort(ets:tab2list(?CACHE)),
     ddoc_cache:open_doc(DbName, ?FOOBAR),
-    [Entry2] = ets:lookup(?CACHE, ets:first(?CACHE)),
-    ?assertEqual(Entry1, Entry2).
+    meck:wait(ddoc_cache_ev, event, [accessed, '_'], 1000),
+    Tab2 = lists:sort(ets:tab2list(?CACHE)),
+    ?assertEqual(Tab2, Tab1).
 
 
 dont_cache_not_found({DbName, _}) ->
diff --git a/src/ddoc_cache/test/ddoc_cache_entry_test.erl b/src/ddoc_cache/test/ddoc_cache_entry_test.erl
index e593bf7..381185c 100644
--- a/src/ddoc_cache/test/ddoc_cache_entry_test.erl
+++ b/src/ddoc_cache/test/ddoc_cache_entry_test.erl
@@ -61,7 +61,7 @@ check_entry_test_() ->
 cancel_and_replace_opener(_) ->
     Key = {ddoc_cache_entry_custom, {<<"foo">>, ?MODULE}},
     true = ets:insert_new(?CACHE, #entry{key = Key}),
-    {ok, Entry} = ddoc_cache_entry:start_link(Key),
+    {ok, Entry} = ddoc_cache_entry:start_link(Key, undefined),
     Opener1 = element(4, sys:get_state(Entry)),
     Ref1 = erlang:monitor(process, Opener1),
     gen_server:cast(Entry, force_refresh),
@@ -78,7 +78,7 @@ condenses_access_messages({DbName, _}) ->
     meck:reset(ddoc_cache_ev),
     Key = {ddoc_cache_entry_custom, {DbName, ?MODULE}},
     true = ets:insert(?CACHE, #entry{key = Key}),
-    {ok, Entry} = ddoc_cache_entry:start_link(Key),
+    {ok, Entry} = ddoc_cache_entry:start_link(Key, undefined),
     erlang:suspend_process(Entry),
     lists:foreach(fun(_) ->
         gen_server:cast(Entry, accessed)
@@ -105,7 +105,7 @@ evict_when_not_accessed(_) ->
     meck:reset(ddoc_cache_ev),
     Key = {ddoc_cache_entry_custom, {<<"bar">>, ?MODULE}},
     true = ets:insert_new(?CACHE, #entry{key = Key}),
-    {ok, Entry} = ddoc_cache_entry:start_link(Key),
+    {ok, Entry} = ddoc_cache_entry:start_link(Key, undefined),
     Ref = erlang:monitor(process, Entry),
     ?assertEqual(1, element(7, sys:get_state(Entry))),
     ok = gen_server:cast(Entry, refresh),
diff --git a/src/ddoc_cache/test/ddoc_cache_eviction_test.erl b/src/ddoc_cache/test/ddoc_cache_eviction_test.erl
index 0b9f57b..30b4fb7 100644
--- a/src/ddoc_cache/test/ddoc_cache_eviction_test.erl
+++ b/src/ddoc_cache/test/ddoc_cache_eviction_test.erl
@@ -86,8 +86,10 @@ check_upgrade_clause({DbName, _}) ->
     ddoc_cache_tutil:clear(),
     meck:reset(ddoc_cache_ev),
     {ok, _} = ddoc_cache:open_doc(DbName, ?FOOBAR),
-    ?assertEqual(1, ets:info(?CACHE, size)),
+    meck:wait(ddoc_cache_ev, event, [started, '_'], 1000),
+    meck:wait(ddoc_cache_ev, event, [default_started, '_'], 1000),
+    ?assertEqual(2, ets:info(?CACHE, size)),
     gen_server:cast(ddoc_cache_opener, {do_evict, DbName}),
     meck:wait(ddoc_cache_ev, event, [evicted, DbName], 1000),
-    meck:wait(ddoc_cache_ev, event, [removed, '_'], 1000),
+    meck:wait(2, ddoc_cache_ev, event, [removed, '_'], 1000),
     ?assertEqual(0, ets:info(?CACHE, size)).
diff --git a/src/ddoc_cache/test/ddoc_cache_no_cache_test.erl b/src/ddoc_cache/test/ddoc_cache_no_cache_test.erl
index a5a5751..637a6e8 100644
--- a/src/ddoc_cache/test/ddoc_cache_no_cache_test.erl
+++ b/src/ddoc_cache/test/ddoc_cache_no_cache_test.erl
@@ -20,6 +20,7 @@
 ddoc(DDocId) ->
     {ok, #doc{
         id = DDocId,
+        revs = {1, [<<"deadbeefdeadbeef">>]},
         body = {[
             {<<"ohai">>, null}
         ]}
diff --git a/src/ddoc_cache/test/ddoc_cache_open_error_test.erl b/src/ddoc_cache/test/ddoc_cache_open_error_test.erl
index 0ac2390..f3a9b10 100644
--- a/src/ddoc_cache/test/ddoc_cache_open_error_test.erl
+++ b/src/ddoc_cache/test/ddoc_cache_open_error_test.erl
@@ -31,7 +31,7 @@ stop_couch(Ctx) ->
     ddoc_cache_tutil:stop_couch(Ctx).
 
 
-check_basic_test_() ->
+check_open_error_test_() ->
     {
         setup,
         fun start_couch/0,
diff --git a/src/ddoc_cache/test/ddoc_cache_refresh_test.erl b/src/ddoc_cache/test/ddoc_cache_refresh_test.erl
index 7bc1704..f145987 100644
--- a/src/ddoc_cache/test/ddoc_cache_refresh_test.erl
+++ b/src/ddoc_cache/test/ddoc_cache_refresh_test.erl
@@ -58,8 +58,11 @@ refresh_ddoc({DbName, _}) ->
     ddoc_cache_tutil:clear(),
     meck:reset(ddoc_cache_ev),
     {ok, _} = ddoc_cache:open_doc(DbName, ?FOOBAR),
-    ?assertEqual(1, ets:info(?CACHE, size)),
-    [#entry{key = Key, val = DDoc}] = ets:tab2list(?CACHE),
+    meck:wait(ddoc_cache_ev, event, [started, '_'], 1000),
+    meck:wait(ddoc_cache_ev, event, [default_started, '_'], 1000),
+
+    ?assertEqual(2, ets:info(?CACHE, size)),
+    [#entry{key = Key, val = DDoc}, _] = lists:sort(ets:tab2list(?CACHE)),
     NewDDoc = DDoc#doc{
         body = {[{<<"foo">>, <<"baz">>}]}
     },
@@ -69,7 +72,7 @@ refresh_ddoc({DbName, _}) ->
     },
     meck:wait(ddoc_cache_ev, event, [updated, {Key, Expect}], 1000),
     ?assertMatch({ok, Expect}, ddoc_cache:open_doc(DbName, ?FOOBAR)),
-    ?assertEqual(1, ets:info(?CACHE, size)).
+    ?assertEqual(2, ets:info(?CACHE, size)).
 
 
 refresh_ddoc_rev({DbName, _}) ->
@@ -77,7 +80,11 @@ refresh_ddoc_rev({DbName, _}) ->
     meck:reset(ddoc_cache_ev),
     Rev = ddoc_cache_tutil:get_rev(DbName, ?FOOBAR),
     {ok, RevDDoc} = ddoc_cache:open_doc(DbName, ?FOOBAR, Rev),
-    [#entry{key = Key, val = DDoc}] = ets:tab2list(?CACHE),
+
+    meck:wait(ddoc_cache_ev, event, [started, '_'], 1000),
+    meck:wait(ddoc_cache_ev, event, [default_started, '_'], 1000),
+
+    [_, #entry{key = Key, val = DDoc}] = lists:sort(ets:tab2list(?CACHE)),
     NewDDoc = DDoc#doc{
         body = {[{<<"foo">>, <<"kazam">>}]}
     },
@@ -86,7 +93,7 @@ refresh_ddoc_rev({DbName, _}) ->
     % getting the same original response from the cache
     meck:wait(ddoc_cache_ev, event, [update_noop, Key], 1000),
     ?assertMatch({ok, RevDDoc}, ddoc_cache:open_doc(DbName, ?FOOBAR, Rev)),
-    ?assertEqual(1, ets:info(?CACHE, size)).
+    ?assertEqual(2, ets:info(?CACHE, size)).
 
 
 refresh_vdu({DbName, _}) ->
diff --git a/src/ddoc_cache/test/ddoc_cache_remove_test.erl b/src/ddoc_cache/test/ddoc_cache_remove_test.erl
index 7596b99..8787482 100644
--- a/src/ddoc_cache/test/ddoc_cache_remove_test.erl
+++ b/src/ddoc_cache/test/ddoc_cache_remove_test.erl
@@ -67,16 +67,26 @@ remove_ddoc({DbName, _}) ->
     meck:reset(ddoc_cache_ev),
     ?assertEqual(0, ets:info(?CACHE, size)),
     {ok, _} = ddoc_cache:open_doc(DbName, ?FOOBAR),
-    ?assertEqual(1, ets:info(?CACHE, size)),
-    [#entry{key = Key, val = DDoc}] = ets:tab2list(?CACHE),
+
+    meck:wait(ddoc_cache_ev, event, [started, '_'], 1000),
+    meck:wait(ddoc_cache_ev, event, [default_started, '_'], 1000),
+
+    [#entry{val = DDoc}, #entry{val = DDoc}] = ets:tab2list(?CACHE),
+    {Depth, [RevId | _]} = DDoc#doc.revs,
     NewDDoc = DDoc#doc{
         deleted = true,
         body = {[]}
     },
     {ok, _} = fabric:update_doc(DbName, NewDDoc, [?ADMIN_CTX]),
-    meck:wait(ddoc_cache_ev, event, [removed, Key], 1000),
+
+    DDocIdKey = {ddoc_cache_entry_ddocid, {DbName, ?FOOBAR}},
+    Rev = {Depth, RevId},
+    DDocIdRevKey = {ddoc_cache_entry_ddocid_rev, {DbName, ?FOOBAR, Rev}},
+    meck:wait(ddoc_cache_ev, event, [removed, DDocIdKey], 1000),
+    meck:wait(ddoc_cache_ev, event, [update_noop, DDocIdRevKey], 1000),
+
     ?assertMatch({not_found, deleted}, ddoc_cache:open_doc(DbName, ?FOOBAR)),
-    ?assertEqual(0, ets:info(?CACHE, size)).
+    ?assertEqual(1, ets:info(?CACHE, size)).
 
 
 remove_ddoc_rev({DbName, _}) ->
@@ -84,7 +94,15 @@ remove_ddoc_rev({DbName, _}) ->
     meck:reset(ddoc_cache_ev),
     Rev = ddoc_cache_tutil:get_rev(DbName, ?VDU),
     {ok, _} = ddoc_cache:open_doc(DbName, ?VDU, Rev),
-    [#entry{key = Key, val = DDoc, pid = Pid}] = ets:tab2list(?CACHE),
+
+    meck:wait(ddoc_cache_ev, event, [started, '_'], 1000),
+    meck:wait(ddoc_cache_ev, event, [default_started, '_'], 1000),
+
+    % Notice the sort so that we know we're getting the
+    % revid version second.
+    [_, #entry{key = Key, val = DDoc, pid = Pid}]
+            = lists:sort(ets:tab2list(?CACHE)),
+
     NewDDoc = DDoc#doc{
         body = {[{<<"an">>, <<"update">>}]}
     },
@@ -101,7 +119,7 @@ remove_ddoc_rev({DbName, _}) ->
             {{not_found, missing}, _},
             ddoc_cache:open_doc(DbName, ?VDU, Rev)
         ),
-    ?assertEqual(0, ets:info(?CACHE, size)).
+    ?assertEqual(1, ets:info(?CACHE, size)).
 
 
 remove_ddoc_rev_only({DbName, _}) ->

-- 
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.