diff options
author | Paul J. Davis <paul.joseph.davis@gmail.com> | 2019-03-26 17:51:18 -0500 |
---|---|---|
committer | Paul J. Davis <paul.joseph.davis@gmail.com> | 2019-03-26 17:51:18 -0500 |
commit | 971bb98989c7226bb96f38e13cb4a61acbbb12d2 (patch) | |
tree | 5c08e6a5d0a6fe439a9ddec79e8cac348823371a | |
parent | 628795ab535e05531fd35db29564979284184b2f (diff) | |
download | couchdb-971bb98989c7226bb96f38e13cb4a61acbbb12d2.tar.gz |
Bug fixes
-rw-r--r-- | FDB_NOTES.md | 3 | ||||
-rw-r--r-- | src/chttpd/src/chttpd_auth_request.erl | 6 | ||||
-rw-r--r-- | src/chttpd/src/chttpd_db.erl | 64 | ||||
-rw-r--r-- | src/fabric/src/fabric2_db.erl | 85 | ||||
-rw-r--r-- | src/fabric/src/fabric2_fdb.erl | 48 | ||||
-rw-r--r-- | src/fabric/src/fabric2_server.erl | 6 |
6 files changed, 102 insertions, 110 deletions
diff --git a/FDB_NOTES.md b/FDB_NOTES.md index 62faf651f..86fec262d 100644 --- a/FDB_NOTES.md +++ b/FDB_NOTES.md @@ -55,4 +55,5 @@ Things of Note would require us having the entire FDI, however it'd be wasteful to return all of that in an open_revs call, but bug compatibility ftw!) -12.
\ No newline at end of file +12. Is it possible that a server_admin can delete a db without being able + to open it? If so that's probably changed behavior.
\ No newline at end of file diff --git a/src/chttpd/src/chttpd_auth_request.erl b/src/chttpd/src/chttpd_auth_request.erl index c9ca18d70..77a800500 100644 --- a/src/chttpd/src/chttpd_auth_request.erl +++ b/src/chttpd/src/chttpd_auth_request.erl @@ -101,7 +101,8 @@ server_authorization_check(#httpd{path_parts=[<<"_", _/binary>>|_]}=Req) -> require_admin(Req). db_authorization_check(#httpd{path_parts=[DbName|_],user_ctx=Ctx}=Req) -> - fabric_security:check_is_member(DbName, Ctx), + {ok, Db} = fabric2_db:open(DbName, [{user_ctx, Ctx}]), + fabric2_db:check_is_member(Db), Req. require_admin(Req) -> @@ -109,7 +110,8 @@ require_admin(Req) -> Req. require_db_admin(#httpd{path_parts=[DbName|_],user_ctx=Ctx}=Req) -> - Sec = fabric2:get_security(DbName), + {ok, Db} = fabric2_db:open(DbName, [{user_ctx, Ctx}]), + Sec = fabric2_db:get_security(Db), case is_db_admin(Ctx,Sec) of true -> Req; false -> throw({unauthorized, <<"You are not a server or db admin.">>}) diff --git a/src/chttpd/src/chttpd_db.erl b/src/chttpd/src/chttpd_db.erl index bf7b8691e..4c2e33eae 100644 --- a/src/chttpd/src/chttpd_db.erl +++ b/src/chttpd/src/chttpd_db.erl @@ -351,8 +351,8 @@ handle_design_info_req(Req, _Db, _DDoc) -> create_db_req(#httpd{}=Req, DbName) -> couch_httpd:verify_is_server_admin(Req), DocUrl = absolute_uri(Req, "/" ++ couch_util:url_encode(DbName)), - case fabric2:create_db(DbName) of - ok -> + case fabric2_db:create(DbName, []) of + {ok, _} -> send_json(Req, 201, [{"Location", DocUrl}], {[{ok, true}]}); {error, file_exists} -> chttpd:send_error(Req, file_exists); @@ -362,7 +362,7 @@ create_db_req(#httpd{}=Req, DbName) -> delete_db_req(#httpd{}=Req, DbName) -> couch_httpd:verify_is_server_admin(Req), - case fabric2:delete_db(DbName, []) of + case fabric2_db:delete(DbName, []) of ok -> send_json(Req, 200, {[{ok, true}]}); Error -> @@ -370,13 +370,13 @@ delete_db_req(#httpd{}=Req, DbName) -> end. do_db_req(#httpd{path_parts=[DbName|_], user_ctx=Ctx}=Req, Fun) -> - Db = fabric2:open_db(DbName, [{user_ctx, Ctx}]), + {ok, Db} = fabric2_db:open(DbName, [{user_ctx, Ctx}]), Fun(Req, Db). db_req(#httpd{method='GET',path_parts=[DbName]}=Req, Db) -> % measure the time required to generate the etag, see if it's worth it T0 = os:timestamp(), - {ok, DbInfo} = fabric2:get_db_info(Db), + {ok, DbInfo} = fabric2_db:get_db_info(Db), DeltaT = timer:now_diff(os:timestamp(), T0) / 1000, couch_stats:update_histogram([couchdb, dbinfo], DeltaT), send_json(Req, {DbInfo}); @@ -399,7 +399,7 @@ db_req(#httpd{method='POST', path_parts=[DbName], user_ctx=Ctx}=Req, Db) -> "ok" -> % async_batching spawn(fun() -> - case catch(fabric2:update_doc(Db, Doc2, Options)) of + case catch(fabric2_db:update_doc(Db, Doc2, Options)) of {ok, _} -> chttpd_stats:incr_writes(), ok; @@ -419,7 +419,7 @@ db_req(#httpd{method='POST', path_parts=[DbName], user_ctx=Ctx}=Req, Db) -> % normal DocUrl = absolute_uri(Req, [$/, couch_util:url_encode(DbName), $/, couch_util:url_encode(DocId)]), - case fabric2:update_doc(Db, Doc2, Options) of + case fabric2_db:update_doc(Db, Doc2, Options) of {ok, NewRev} -> chttpd_stats:incr_writes(), HttpCode = 201; @@ -494,7 +494,7 @@ db_req(#httpd{method='POST',path_parts=[_,<<"_bulk_docs">>], user_ctx=Ctx}=Req, true -> [all_or_nothing|Options]; _ -> Options end, - case fabric2:update_docs(Db, Docs, Options2) of + case fabric2_db:update_docs(Db, Docs, Options2) of {ok, Results} -> % output the results chttpd_stats:incr_writes(length(Results)), @@ -513,7 +513,7 @@ db_req(#httpd{method='POST',path_parts=[_,<<"_bulk_docs">>], user_ctx=Ctx}=Req, send_json(Req, 417, ErrorsJson) end; false -> - case fabric2:update_docs(Db, Docs, [replicated_changes|Options]) of + case fabric2_db:update_docs(Db, Docs, [replicated_changes|Options]) of {ok, Errors} -> chttpd_stats:incr_writes(length(Docs)), ErrorsJson = lists:map(fun update_doc_result_to_json/1, Errors), @@ -877,7 +877,7 @@ db_doc_req(#httpd{method='GET', mochi_req=MochiReq}=Req, Db, DocId) -> Doc = couch_doc_open(Db, DocId, Rev, Options2), send_doc(Req, Doc, Options2); _ -> - case fabric2:open_revs(Db, DocId, Revs, Options) of + case fabric2_db:open_revs(Db, DocId, Revs, Options) of {ok, []} when Revs == all -> chttpd:send_error(Req, {not_found, missing}); {ok, Results} -> @@ -928,7 +928,7 @@ db_doc_req(#httpd{method='POST', user_ctx=Ctx}=Req, Db, DocId) -> Doc = couch_doc_from_req(Req, Db, DocId, Json); false -> Rev = couch_doc:parse_rev(list_to_binary(couch_util:get_value("_rev", Form))), - Doc = case fabric2:open_revs(Db, DocId, [Rev], []) of + Doc = case fabric2_db:open_revs(Db, DocId, [Rev], []) of {ok, [{ok, Doc0}]} -> chttpd_stats:incr_reads(), Doc0; @@ -957,7 +957,7 @@ db_doc_req(#httpd{method='POST', user_ctx=Ctx}=Req, Db, DocId) -> NewDoc = Doc#doc{ atts = UpdatedAtts ++ OldAtts2 }, - case fabric2:update_doc(Db, NewDoc, Options) of + case fabric2_db:update_doc(Db, NewDoc, Options) of {ok, NewRev} -> chttpd_stats:incr_writes(), HttpCode = 201; @@ -1006,7 +1006,7 @@ db_doc_req(#httpd{method='PUT', user_ctx=Ctx}=Req, Db, DocId) -> Doc = couch_doc_from_req(Req, Db, DocId, chttpd:json_body(Req)), spawn(fun() -> - case catch(fabric2:update_doc(Db, Doc, Options)) of + case catch(fabric2_db:update_doc(Db, Doc, Options)) of {ok, _} -> chttpd_stats:incr_writes(), ok; @@ -1040,7 +1040,7 @@ db_doc_req(#httpd{method='COPY', user_ctx=Ctx}=Req, Db, SourceDocId) -> % open old doc Doc = couch_doc_open(Db, SourceDocId, SourceRev, []), % save new doc - case fabric2:update_doc(Db, + case fabric2_db:update_doc(Db, Doc#doc{id=TargetDocId, revs=TargetRevs}, [{user_ctx,Ctx}]) of {ok, NewTargetRev} -> chttpd_stats:incr_writes(), @@ -1263,31 +1263,7 @@ http_code_from_status(Status) -> end. update_doc(Db, DocId, #doc{deleted=Deleted, body=DocBody}=Doc, Options) -> - {_, Ref} = spawn_monitor(fun() -> - try fabric2:update_doc(Db, Doc, Options) of - Resp -> - exit({exit_ok, Resp}) - catch - throw:Reason -> - exit({exit_throw, Reason}); - error:Reason -> - exit({exit_error, Reason}); - exit:Reason -> - exit({exit_exit, Reason}) - end - end), - Result = receive - {'DOWN', Ref, _, _, {exit_ok, Ret}} -> - Ret; - {'DOWN', Ref, _, _, {exit_throw, Reason}} -> - throw(Reason); - {'DOWN', Ref, _, _, {exit_error, Reason}} -> - erlang:error(Reason); - {'DOWN', Ref, _, _, {exit_exit, Reason}} -> - erlang:exit(Reason) - end, - - case Result of + case fabric2_db:update_doc(Db, Doc, Options) of {ok, NewRev} -> Accepted = false; {accepted, NewRev} -> @@ -1345,7 +1321,7 @@ couch_doc_from_req(Req, Db, DocId, Json) -> couch_doc_open(Db, DocId, Rev, Options) -> case Rev of nil -> % open most recent rev - case fabric2:open_doc(Db, DocId, Options) of + case fabric2_db:open_doc(Db, DocId, Options) of {ok, Doc} -> chttpd_stats:incr_reads(), Doc; @@ -1353,7 +1329,7 @@ couch_doc_open(Db, DocId, Rev, Options) -> throw(Error) end; _ -> % open a specific rev (deletions come back as stubs) - case fabric2:open_revs(Db, DocId, [Rev], Options) of + case fabric2_db:open_revs(Db, DocId, [Rev], Options) of {ok, [{ok, Doc}]} -> chttpd_stats:incr_reads(), Doc; @@ -1529,7 +1505,7 @@ db_attachment_req(#httpd{method=Method, user_ctx=Ctx}=Req, Db, DocId, FileNamePa couch_db:validate_docid(Db, DocId), #doc{id=DocId}; Rev -> - case fabric2:open_revs(Db, DocId, [Rev], [{user_ctx,Ctx}]) of + case fabric2_db:open_revs(Db, DocId, [Rev], [{user_ctx,Ctx}]) of {ok, [{ok, Doc0}]} -> chttpd_stats:incr_reads(), Doc0; @@ -1545,7 +1521,7 @@ db_attachment_req(#httpd{method=Method, user_ctx=Ctx}=Req, Db, DocId, FileNamePa atts = NewAtt ++ [A || A <- Atts, couch_att:fetch(name, A) /= FileName] }, W = chttpd:qs_value(Req, "w", integer_to_list(mem3:quorum(Db))), - case fabric2:update_doc(Db, DocEdited, [{user_ctx,Ctx}, {w,W}]) of + case fabric2_db:update_doc(Db, DocEdited, [{user_ctx,Ctx}, {w,W}]) of {ok, UpdatedRev} -> chttpd_stats:incr_writes(), HttpCode = 201; @@ -1901,7 +1877,7 @@ bulk_get_open_doc_revs1(Db, Props, Options, {DocId, Revs}) -> bulk_get_open_doc_revs1(Db, Props, Options, {DocId, Revs, Options1}) end; bulk_get_open_doc_revs1(Db, Props, _, {DocId, Revs, Options}) -> - case fabric2:open_revs(Db, DocId, Revs, Options) of + case fabric2_db:open_revs(Db, DocId, Revs, Options) of {ok, []} -> RevStr = couch_util:get_value(<<"rev">>, Props), Error = {RevStr, <<"not_found">>, <<"missing">>}, diff --git a/src/fabric/src/fabric2_db.erl b/src/fabric/src/fabric2_db.erl index d172209bd..88f6bd953 100644 --- a/src/fabric/src/fabric2_db.erl +++ b/src/fabric/src/fabric2_db.erl @@ -124,7 +124,7 @@ -include_lib("couch/include/couch_db.hrl"). --include_lib("fabric/include/fabric2.hrl"). +-include("fabric2.hrl"). -define(DBNAME_REGEX, @@ -138,18 +138,19 @@ create(DbName, Options) -> Result = transactional(DbName, Options, fun(TxDb) -> - case fabric2_fdb:db_exists(TxDb) of + case fabric2_fdb:exists(TxDb) of true -> {error, file_exists}; false -> - fabric2_fdb:db_create(TxDb) + fabric2_fdb:create(TxDb, Options) end end), % We cache outside of the transaction so that we're sure % that this request created the database case Result of #{} = Db -> - fabric2_server:store(Db); + ok = fabric2_server:store(Db), + {ok, Db#{tx => undefined}}; Error -> Error end. @@ -159,27 +160,29 @@ open(DbName, Options) -> case fabric2_server:fetch(DbName) of #{} = Db -> with_tx(Db, fun(TxDb) -> - case fabric2_fdb:db_is_current(TxDb) of + case fabric2_fdb:is_current(TxDb) of true -> - Db; + {ok, maybe_set_user_ctx(Db, Options)}; false -> - Reopened = fabric2_fdb:db_open(TxDb), - fabric2_server:store(Reopened) + Reopened = fabric2_fdb:open(TxDb, Options), + ok = fabric2_server:store(Reopened), + {ok, Reopened} end end); undefined -> transactional(DbName, Options, fun(TxDb) -> - Opened = fabric2_fdb:db_open(TxDb), - fabric2_server:store(Opened) + Opened = fabric2_fdb:open(TxDb, Options), + ok = fabric2_server:store(Opened), + {ok, Opened#{tx => undefined}} end) end. delete(DbName, Options) -> % This will throw if the db does not exist - Db = open(DbName, Options), + {ok, Db} = open(DbName, Options), with_tx(Db, fun(TxDb) -> - fabric2_fdb:db_delete(TxDb) + fabric2_fdb:delete(TxDb) end). @@ -237,7 +240,7 @@ get_compactor_pid(#{} = _Db) -> get_db_info(#{} = Db) -> DbProps = with_tx(Db, fun(TxDb) -> - fabric2_fdb:db_get_info(TxDb) + fabric2_fdb:get_info(TxDb) end), BaseProps = [ @@ -296,7 +299,7 @@ get_security(#{security_doc := SecurityDoc}) -> get_update_seq(#{} = Db) -> - case fabric2_fdb:db_get_changes(Db, [{limit, 1}, {reverse, true}]) of + case fabric2_fdb:get_changes(Db, [{limit, 1}, {reverse, true}]) of [] -> fabric2_util:to_hex(<<0:80>>); [{Seq, _}] -> @@ -346,14 +349,14 @@ is_system_db_name(DbName) when is_binary(DbName) -> set_revs_limit(#{} = Db, RevsLimit) -> RevsLimBin = ?uint2bin(RevsLimit), with_tx(Db, fun(TxDb) -> - fabric2_fdb:db_set_config(TxDb, <<"revs_limit">>, RevsLimBin) + fabric2_fdb:set_config(TxDb, <<"revs_limit">>, RevsLimBin) end). set_security(#{} = Db, Security) -> SecBin = ?JSON_ENCODE(Security), with_tx(Db, fun(TxDb) -> - fabric2_fdb:db_set_config(TxDb, <<"security_doc">>, SecBin) + fabric2_fdb:set_config(TxDb, <<"security_doc">>, SecBin) end). @@ -388,36 +391,35 @@ open_doc(#{} = Db, DocId, _Options) -> end). -open_doc_revs(Db, FDI, Revs, Options) -> - #full_doc_info{ - id = Id, - rev_tree = RevTree - } = FDI, +open_doc_revs(Db, DocId, Revs, Options) -> Latest = lists:member(latest, Options), - {Found, Missing} = case Revs of - all -> - {couch_key_tree:get_all_leafs(RevTree), []}; - _ when Latest -> - couch_key_tree:get_key_leafs(RevTree, Revs); - _ -> - couch_key_tree:get(RevTree, Revs) - end, - Docs = with_tx(Db, fun(TxDb) -> - lists:map(fun({Value, {Pos, [Rev | _]} = RevPath}) -> + with_tx(Db, fun(TxDb) -> + #full_doc_info{ + rev_tree = RevTree + } = fabric2_db:get_full_doc_info(TxDb, DocId), + {Found, Missing} = case Revs of + all -> + {couch_key_tree:get_all_leafs(RevTree), []}; + _ when Latest -> + couch_key_tree:get_key_leafs(RevTree, Revs); + _ -> + couch_key_tree:get(RevTree, Revs) + end, + Docs = lists:map(fun({Value, {Pos, [Rev | _]} = RevPath}) -> case Value of ?REV_MISSING -> % We have the rev in our list but know nothing about it {{not_found, missing}, {Pos, Rev}}; _ -> - case fabric2_fdb:get_doc_body(TxDb, Id, RevPath) of + case fabric2_fdb:get_doc_body(TxDb, DocId, RevPath) of #doc{} = Doc -> {ok, Doc}; Else -> {Else, {Pos, Rev}} end end - end, Found) - end), - MissingDocs = [{{not_found, missing}, MRev} || MRev <- Missing], - {ok, Docs ++ MissingDocs}. + end, Found), + MissingDocs = [{{not_found, missing}, MRev} || MRev <- Missing], + {ok, Docs ++ MissingDocs} + end). update_doc(Db, Doc) -> @@ -477,6 +479,15 @@ new_revid(Doc) -> Doc#doc{revs = {OldStart + 1, [Rev | OldRevs]}}. +maybe_set_user_ctx(Db, Options) -> + case fabric2_util:get_value(user_ctx, Options) of + #user_ctx{} = UserCtx -> + set_user_ctx(Db, UserCtx); + undefined -> + Db + end. + + is_member(Db) -> {SecProps} = get_security(Db), case is_admin(Db) of @@ -589,7 +600,7 @@ update_doc_int(#{} = Db, #doc{} = Doc0, Options) -> end, NewExists = not FDI3#full_doc_info.deleted, - ok = fabric2_fdb:write_doc(Db, FDI3, Doc3), + ok = fabric2_fdb:store_doc(Db, FDI3, Doc3), case {OldExists, NewExists} of {false, true} -> diff --git a/src/fabric/src/fabric2_fdb.erl b/src/fabric/src/fabric2_fdb.erl index e5bd81a63..68d148ea0 100644 --- a/src/fabric/src/fabric2_fdb.erl +++ b/src/fabric/src/fabric2_fdb.erl @@ -16,8 +16,8 @@ -export([ init/3, - create/1, - open/1, + create/2, + open/2, delete/1, exists/1, is_current/1, @@ -71,15 +71,15 @@ % Various utility macros --define(REQUIRE_TX(Db), {erlfdb_transaction, _} = maps:get(Db, tx)). +-define(REQUIRE_TX(Db), {erlfdb_transaction, _} = maps:get(tx, Db)). -define(REQUIRE_CURRENT(Db), true = is_current(Db)). -define(UNSET_VS, {versionstamp, 16#FFFFFFFFFFFFFFFF, 16#FFFF}). init(Tx, DbName, Options) -> - Root = erlfdb_directory:get_root(), - CouchDB = erlfdb_directory:create_or_open(Root, [<<"couchdb">>]), + Root = erlfdb_directory:root(), + CouchDB = erlfdb_directory:create_or_open(Tx, Root, [<<"couchdb">>]), Prefix = erlfdb_directory:get_name(CouchDB), #{ name => DbName, @@ -89,7 +89,7 @@ init(Tx, DbName, Options) -> }. -create(#{} = Db) -> +create(#{} = Db, Options) -> ?REQUIRE_TX(Db), #{ name := DbName, @@ -120,17 +120,18 @@ create(#{} = Db) -> erlfdb:set(Tx, Key, V) end, Defaults), + UserCtx = fabric2_util:get_value(user_ctx, Options, #user_ctx{}), Version = erlfdb:wait(erlfdb:get(Tx, ?METADATA_VERSION_KEY)), Db#{ uuid => UUID, db_prefix => DbPrefix, - version => Version, + md_version => Version, revs_limit => 1000, security_doc => {[]}, validate_doc_update_funs => [], - user_ctx => #user_ctx{}, + user_ctx => UserCtx, before_doc_update => undefined, after_doc_update => undefined @@ -138,7 +139,7 @@ create(#{} = Db) -> }. -open(#{} = Db0) -> +open(#{} = Db0, Options) -> ?REQUIRE_TX(Db0), #{ name := DbName, @@ -152,13 +153,14 @@ open(#{} = Db0) -> not_found -> erlang:error(database_does_not_exist) end, + UserCtx = fabric2_util:get_value(user_ctx, Options, #user_ctx{}), Version = erlfdb:wait(erlfdb:get(Tx, ?METADATA_VERSION_KEY)), Db1 = Db0#{ - db_preix => DbPrefix, - version => Version, + db_prefix => DbPrefix, + md_version => Version, - user_ctx => #user_ctx{}, + user_ctx => UserCtx, % Place holders until we implement these % bits. @@ -167,14 +169,14 @@ open(#{} = Db0) -> after_doc_read => undefined }, - lists:foldl(fun({Key, Val}) -> + lists:foldl(fun({Key, Val}, DbAcc) -> case Key of <<"uuid">> -> - Db1#{uuid => Val}; + DbAcc#{uuid => Val}; <<"revs_limit">> -> - Db1#{revs_limit => ?bin2uint(Val)}; + DbAcc#{revs_limit => ?bin2uint(Val)}; <<"security_doc">> -> - Db1#{security_doc => ?JSON_DECODE(Val)} + DbAcc#{security_doc => ?JSON_DECODE(Val)} end end, Db1, get_config(Db1)). @@ -188,10 +190,10 @@ delete(#{} = Db) -> db_prefix := DbPrefix } = Db, - DbKey = erlfdb_tuple:pack({?DBS, DbName}, LayerPrefix), + DbKey = erlfdb_tuple:pack({?ALL_DBS, DbName}, LayerPrefix), erlfdb:clear(Tx, DbKey), erlfdb:clear_range_startswith(Tx, DbPrefix), - bump_metadata_version(Db), + bump_metadata_version(Tx), ok. @@ -229,14 +231,14 @@ get_info(#{} = Db) -> db_prefix := DbPrefix } = Db, - {CStart, CEnd} = erlfdb_tuple:pack({?DB_CHANGES}, DbPrefix), + {CStart, CEnd} = erlfdb_tuple:range({?DB_CHANGES}, DbPrefix), ChangesFuture = erlfdb:get_range(Tx, CStart, CEnd, [ {streaming_mode, exact}, {limit, 1}, {reverse, true} ]), - StatsPrefix = erlfdb_tuple:pack(?DB_STATS, DbPrefix), + StatsPrefix = erlfdb_tuple:pack({?DB_STATS}, DbPrefix), MetaFuture = erlfdb:get_range_startswith(Tx, StatsPrefix), RawSeq = case erlfdb:wait(ChangesFuture) of @@ -279,10 +281,10 @@ get_config(#{} = Db) -> db_prefix := DbPrefix } = Db, - {Start, End} = erlfdb_tuple:pack({?DB_CONFIG}, DbPrefix), + {Start, End} = erlfdb_tuple:range({?DB_CONFIG}, DbPrefix), Future = erlfdb:get_range(Tx, Start, End), - lists:map(fun(K, V) -> + lists:map(fun({K, V}) -> {?DB_CONFIG, Key} = erlfdb_tuple:unpack(K, DbPrefix), {Key, V} end, erlfdb:wait(Future)). @@ -389,7 +391,7 @@ get_changes(#{} = Db, Options) -> db_prefix := DbPrefix } = Db, - {CStart, CEnd} = erlfdb_tuple:pack({?DB_CHANGES}, DbPrefix), + {CStart, CEnd} = erlfdb_tuple:range({?DB_CHANGES}, DbPrefix), Future = erlfdb:get_range(Tx, CStart, CEnd, Options), lists:map(fun({Key, Val}) -> {?DB_CHANGES, Seq} = erlfdb_tuple:unpack(Key, DbPrefix), diff --git a/src/fabric/src/fabric2_server.erl b/src/fabric/src/fabric2_server.erl index 9a0e4fac2..1e086ca99 100644 --- a/src/fabric/src/fabric2_server.erl +++ b/src/fabric/src/fabric2_server.erl @@ -51,11 +51,11 @@ fetch(DbName) when is_binary(DbName) -> store(#{name := DbName} = Db0) when is_binary(DbName) -> Db1 = Db0#{ - tx => undefined, - user_ctx => #user_ctx{} + tx := undefined, + user_ctx := #user_ctx{} }, true = ets:insert(?MODULE, {DbName, Db1}), - Db1. + ok. init(_) -> |