You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by va...@apache.org on 2019/08/22 20:02:32 UTC

[couchdb] branch prototype/fdb-layer-fix-db-reopen created (now a7bd1f6)

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

vatamane pushed a change to branch prototype/fdb-layer-fix-db-reopen
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


      at a7bd1f6  Fix DB reopen behavior

This branch includes the following new commits:

     new a7bd1f6  Fix DB reopen behavior

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[couchdb] 01/01: Fix DB reopen behavior

Posted by va...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

vatamane pushed a commit to branch prototype/fdb-layer-fix-db-reopen
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit a7bd1f6cda2198672ded096ee49b5ad32403d8b9
Author: Nick Vatamaniuc <va...@apache.org>
AuthorDate: Thu Aug 22 15:53:15 2019 -0400

    Fix DB reopen behavior
    
    Previously if a VDU was updated in the `before_doc_update/3` handlers, the Db
    handle wasn't refreshed soon enough such that the `prepare_and_validate/3`
    would not see the newly update VDU and would not run it.
    
    To fix make a stale Db throws an exception which bubbles up all the way to
    `fabric2_fdb:transactional/2` where the transaction is retried again with a
    reopened Db.
    
    During `reopen/1` make sure to properly transfer the `user_ctx` property to the
    new handle, and also make sure `user_ctx` is removed from `db_options` to avoid
    caching it in `fabric2_server`.
---
 src/fabric/src/fabric2_fdb.erl | 36 ++++++++++++++++++++++++++----------
 1 file changed, 26 insertions(+), 10 deletions(-)

diff --git a/src/fabric/src/fabric2_fdb.erl b/src/fabric/src/fabric2_fdb.erl
index c58b5f6..df37096 100644
--- a/src/fabric/src/fabric2_fdb.erl
+++ b/src/fabric/src/fabric2_fdb.erl
@@ -78,10 +78,22 @@ transactional(DbName, Options, Fun) when is_binary(DbName) ->
 
 
 transactional(#{tx := undefined} = Db, Fun) ->
-    #{layer_prefix := LayerPrefix} = Db,
-    do_transaction(fun(Tx) ->
-        Fun(Db#{tx => Tx})
-    end, LayerPrefix);
+    try
+        Reopen = maps:get(reopen, Db, false),
+        Db1 = maps:remove(reopen, Db),
+        LayerPrefix = case Reopen of
+            true -> undefined;
+            false -> maps:get(layer_prefix, Db1)
+        end,
+        do_transaction(fun(Tx) ->
+            case Reopen of
+                true -> Fun(reopen(Db1#{tx => Tx}));
+                false -> Fun(Db1#{tx => Tx})
+            end
+        end, LayerPrefix)
+    catch throw:{?MODULE, reopen} ->
+        transactional(Db#{reopen => true}, Fun)
+    end;
 
 transactional(#{tx := {erlfdb_transaction, _}} = Db, Fun) ->
     Fun(Db).
@@ -150,6 +162,7 @@ create(#{} = Db0, Options) ->
     end, Defaults),
 
     UserCtx = fabric2_util:get_value(user_ctx, Options, #user_ctx{}),
+    Options1 = lists:keydelete(user_ctx, 1, Options),
 
     Db#{
         uuid => UUID,
@@ -165,7 +178,7 @@ create(#{} = Db0, Options) ->
         after_doc_read => undefined,
         % All other db things as we add features,
 
-        db_options => Options
+        db_options => Options1
     }.
 
 
@@ -186,6 +199,7 @@ open(#{} = Db0, Options) ->
     DbVersion = erlfdb:wait(erlfdb:get(Tx, DbVersionKey)),
 
     UserCtx = fabric2_util:get_value(user_ctx, Options, #user_ctx{}),
+    Options1 = lists:keydelete(user_ctx, 1, Options),
 
     Db2 = Db1#{
         db_prefix => DbPrefix,
@@ -201,7 +215,7 @@ open(#{} = Db0, Options) ->
         before_doc_update => undefined,
         after_doc_read => undefined,
 
-        db_options => Options
+        db_options => Options1
     },
 
     Db3 = lists:foldl(fun({Key, Val}, DbAcc) ->
@@ -223,9 +237,11 @@ reopen(#{} = OldDb) ->
     #{
         tx := Tx,
         name := DbName,
-        db_options := Options
+        db_options := Options,
+        user_ctx := UserCtx
     } = OldDb,
-    open(init_db(Tx, DbName, Options), Options).
+    Options1 = lists:keystore(user_ctx, 1, Options, {user_ctx, UserCtx}),
+    open(init_db(Tx, DbName, Options1), Options1).
 
 
 delete(#{} = Db) ->
@@ -1132,7 +1148,7 @@ ensure_current(#{} = Db, CheckDbVersion) ->
 
     case erlfdb:wait(erlfdb:get(Tx, ?METADATA_VERSION_KEY)) of
         MetaDataVersion -> Db;
-        _NewVersion -> reopen(Db)
+        _NewVersion -> throw({?MODULE, reopen})
     end,
 
     AlreadyChecked = get(?PDICT_CHECKED_DB_IS_CURRENT),
@@ -1150,7 +1166,7 @@ ensure_current(#{} = Db, CheckDbVersion) ->
                 Db;
             _NewDBVersion ->
                 fabric2_server:remove(maps:get(name, Db)),
-                reopen(Db)
+                throw({?MODULE, reopen})
         end
     end.