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 2020/04/14 22:00:34 UTC
[couchdb] branch allow-using-cached-security-docs created (now
03e82a1)
This is an automated email from the ASF dual-hosted git repository.
vatamane pushed a change to branch allow-using-cached-security-docs
in repository https://gitbox.apache.org/repos/asf/couchdb.git.
at 03e82a1 Allow using cached db handle when reading security and revs_limit properties
This branch includes the following new commits:
new 03e82a1 Allow using cached db handle when reading security and revs_limit properties
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: Allow using cached db handle when reading security
and revs_limit properties
Posted by va...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
vatamane pushed a commit to branch allow-using-cached-security-docs
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 03e82a1beaa59180293bb228c9df70ae7e8dea3b
Author: Nick Vatamaniuc <va...@apache.org>
AuthorDate: Tue Apr 14 17:43:04 2020 -0400
Allow using cached db handle when reading security and revs_limit properties
By default transactions are started every time to check metadata and possibly
reopen the db, but if a `max_age` option is provided then the handle is allowed
to be up to `max_age` milliseconds old.
The main use of this would be in pluggable authorization handlers where it
might be necessary to inspect the security doc multiple times for the same
request before a final decision is made.
`revs_limit/1` was updated as well, mainly for consistency since it is almost
identical to `get_security/1`.
---
src/fabric/src/fabric2_db.erl | 36 ++++++++++++++++++++++++-------
src/fabric/src/fabric2_fdb.erl | 2 ++
src/fabric/test/fabric2_db_misc_tests.erl | 25 +++++++++++++++++++++
3 files changed, 55 insertions(+), 8 deletions(-)
diff --git a/src/fabric/src/fabric2_db.erl b/src/fabric/src/fabric2_db.erl
index 9b9efda..6157c64 100644
--- a/src/fabric/src/fabric2_db.erl
+++ b/src/fabric/src/fabric2_db.erl
@@ -50,7 +50,9 @@
get_instance_start_time/1,
get_pid/1,
get_revs_limit/1,
+ get_revs_limit/2,
get_security/1,
+ get_security/2,
get_update_seq/1,
get_user_ctx/1,
get_uuid/1,
@@ -500,17 +502,21 @@ get_pid(#{}) ->
get_revs_limit(#{} = Db) ->
- #{revs_limit := RevsLimit} = fabric2_fdb:transactional(Db, fun(TxDb) ->
- fabric2_fdb:ensure_current(TxDb)
- end),
- RevsLimit.
+ get_revs_limit(#{} = Db, []).
+
+
+get_revs_limit(#{} = Db, Opts) ->
+ CurrentDb = get_cached_db(Db, Opts),
+ maps:get(revs_limit, CurrentDb).
get_security(#{} = Db) ->
- #{security_doc := SecDoc} = fabric2_fdb:transactional(Db, fun(TxDb) ->
- fabric2_fdb:ensure_current(TxDb)
- end),
- SecDoc.
+ get_security(Db, []).
+
+
+get_security(#{} = Db, Opts) ->
+ CurrentDb = get_cached_db(Db, Opts),
+ maps:get(security_doc, CurrentDb).
get_update_seq(#{} = Db) ->
@@ -2037,3 +2043,17 @@ open_json_doc(Db, DocId, OpenOpts, DocOpts) ->
{ok, #doc{} = Doc} ->
[{doc, couch_doc:to_json_obj(Doc, DocOpts)}]
end.
+
+
+get_cached_db(#{} = Db, Opts) when is_list(Opts) ->
+ MaxAge = fabric2_util:get_value(max_age, Opts, 0),
+ Now = erlang:monotonic_time(millisecond),
+ Age = Now - maps:get(open_ts, Db),
+ case Age < MaxAge of
+ true ->
+ Db;
+ false ->
+ fabric2_fdb:transactional(Db, fun(TxDb) ->
+ fabric2_fdb:ensure_current(TxDb)
+ end)
+ end.
diff --git a/src/fabric/src/fabric2_fdb.erl b/src/fabric/src/fabric2_fdb.erl
index d96c3ae..fc77816 100644
--- a/src/fabric/src/fabric2_fdb.erl
+++ b/src/fabric/src/fabric2_fdb.erl
@@ -231,6 +231,7 @@ create(#{} = Db0, Options) ->
revs_limit => 1000,
security_doc => {[]},
user_ctx => UserCtx,
+ open_ts => erlang:monotonic_time(millisecond),
validate_doc_update_funs => [],
before_doc_update => undefined,
@@ -272,6 +273,7 @@ open(#{} = Db0, Options) ->
security_doc => {[]},
user_ctx => UserCtx,
+ open_ts => erlang:monotonic_time(millisecond),
% Place holders until we implement these
% bits.
diff --git a/src/fabric/test/fabric2_db_misc_tests.erl b/src/fabric/test/fabric2_db_misc_tests.erl
index 1959982..b41c7b0 100644
--- a/src/fabric/test/fabric2_db_misc_tests.erl
+++ b/src/fabric/test/fabric2_db_misc_tests.erl
@@ -38,6 +38,7 @@ misc_test_() ->
?TDEF(accessors),
?TDEF(set_revs_limit),
?TDEF(set_security),
+ ?TDEF(get_security_cached),
?TDEF(is_system_db),
?TDEF(validate_dbname),
?TDEF(validate_doc_ids),
@@ -113,6 +114,30 @@ set_security({DbName, Db, _}) ->
?assertEqual(SecObj, fabric2_db:get_security(Db2)).
+get_security_cached({DbName, Db, _}) ->
+ OldSecObj = fabric2_db:get_security(Db),
+ SecObj = {[
+ {<<"admins">>, {[
+ {<<"names">>, [<<"foo1">>]},
+ {<<"roles">>, []}
+ ]}}
+ ]},
+
+ % Set directly so we don't auto-update the local cache
+ {ok, Db1} = fabric2_db:open(DbName, [?ADMIN_CTX]),
+ ?assertMatch({ok, #{}}, fabric2_fdb:transactional(Db1, fun(TxDb) ->
+ fabric2_fdb:set_config(TxDb, security_doc, SecObj)
+ end)),
+
+ {ok, Db2} = fabric2_db:open(DbName, [?ADMIN_CTX]),
+ ?assertEqual(OldSecObj, fabric2_db:get_security(Db2, [{max_age, 1000}])),
+
+ timer:sleep(100),
+ ?assertEqual(SecObj, fabric2_db:get_security(Db2, [{max_age, 50}])),
+
+ ?assertEqual(ok, fabric2_db:set_security(Db2, OldSecObj)).
+
+
is_system_db({DbName, Db, _}) ->
?assertEqual(false, fabric2_db:is_system_db(Db)),
?assertEqual(false, fabric2_db:is_system_db_name("foo")),