mirror of
https://github.com/valitydev/dmt-client.git
synced 2024-11-06 01:15:22 +00:00
Add formatter (#41)
* Add erlfmt * Apply erlfmt * Update build-utils * Switch to Erlang lib pipe
This commit is contained in:
parent
24e3aad9ce
commit
9e11f50e9c
36
Jenkinsfile
vendored
36
Jenkinsfile
vendored
@ -9,40 +9,14 @@ def finalHook = {
|
|||||||
|
|
||||||
build('dmt_client', 'docker-host', finalHook) {
|
build('dmt_client', 'docker-host', finalHook) {
|
||||||
checkoutRepo()
|
checkoutRepo()
|
||||||
runStage('load_builtils') {
|
loadBuildUtils("builtils")
|
||||||
withGithubSshCredentials {
|
|
||||||
sh 'git submodule update --init'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def pipeDefault
|
def pipeErlangLib
|
||||||
def withWsCache
|
|
||||||
runStage('load pipeline') {
|
runStage('load pipeline') {
|
||||||
env.JENKINS_LIB = "builtils/jenkins_lib"
|
env.JENKINS_LIB = "builtils/jenkins_lib"
|
||||||
pipeDefault = load("${env.JENKINS_LIB}/pipeDefault.groovy")
|
env.SH_TOOLS = "builtils/sh"
|
||||||
withWsCache = load("${env.JENKINS_LIB}/withWsCache.groovy")
|
pipeErlangLib = load("${env.JENKINS_LIB}/pipeErlangLib.groovy")
|
||||||
}
|
|
||||||
|
|
||||||
pipeDefault() {
|
|
||||||
runStage('compile') {
|
|
||||||
withGithubPrivkey {
|
|
||||||
sh 'make wc_compile'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
runStage('lint') {
|
|
||||||
sh 'make wc_lint'
|
|
||||||
}
|
|
||||||
runStage('xref') {
|
|
||||||
sh 'make wc_xref'
|
|
||||||
}
|
|
||||||
runStage('dialyze') {
|
|
||||||
withWsCache("_build/dialyze/rebar3_23.0.1_plt") {
|
|
||||||
sh 'make wc_dialyze'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
runStage('test') {
|
|
||||||
sh "make wdeps_test"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pipeErlangLib.runPipe(true, false, 'dialyze')
|
||||||
}
|
}
|
||||||
|
8
Makefile
8
Makefile
@ -11,7 +11,7 @@ SERVICE_NAME := dmt_client
|
|||||||
# Build image tag to be used
|
# Build image tag to be used
|
||||||
BUILD_IMAGE_TAG := 07d3946f8f005782697de20270ac58cdcd18b011
|
BUILD_IMAGE_TAG := 07d3946f8f005782697de20270ac58cdcd18b011
|
||||||
|
|
||||||
CALL_ANYWHERE := all submodules rebar-update compile xref lint dialyze check clean distclean
|
CALL_ANYWHERE := all submodules rebar-update compile xref lint dialyze check clean distclean check_format format
|
||||||
CALL_W_CONTAINER := $(CALL_ANYWHERE) test
|
CALL_W_CONTAINER := $(CALL_ANYWHERE) test
|
||||||
|
|
||||||
all: compile
|
all: compile
|
||||||
@ -38,6 +38,12 @@ xref: submodules
|
|||||||
lint:
|
lint:
|
||||||
elvis rock
|
elvis rock
|
||||||
|
|
||||||
|
check_format:
|
||||||
|
$(REBAR) fmt -c
|
||||||
|
|
||||||
|
format:
|
||||||
|
$(REBAR) fmt -w
|
||||||
|
|
||||||
dialyze: submodules
|
dialyze: submodules
|
||||||
$(REBAR) as dialyze dialyzer
|
$(REBAR) as dialyze dialyzer
|
||||||
|
|
||||||
|
2
builtils
2
builtils
@ -1 +1 @@
|
|||||||
Subproject commit 1aa72677e975fc0604818362c595dcf84d27c4f0
|
Subproject commit f42e059d9ec93826ba4ad23232eed8ce67bd5486
|
@ -69,6 +69,12 @@
|
|||||||
]}.
|
]}.
|
||||||
|
|
||||||
{plugins, [
|
{plugins, [
|
||||||
|
{erlfmt, "0.8.0"}
|
||||||
|
]}.
|
||||||
|
|
||||||
|
{erlfmt, [
|
||||||
|
{print_width, 120},
|
||||||
|
{files, "{src,include,test}/*.{hrl,erl}"}
|
||||||
]}.
|
]}.
|
||||||
|
|
||||||
{pre_hooks, [
|
{pre_hooks, [
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
%%% @end
|
%%% @end
|
||||||
|
|
||||||
-module(dmt_client).
|
-module(dmt_client).
|
||||||
|
|
||||||
-behaviour(supervisor).
|
-behaviour(supervisor).
|
||||||
-behaviour(application).
|
-behaviour(application).
|
||||||
|
|
||||||
@ -52,15 +53,11 @@
|
|||||||
|
|
||||||
%%% API
|
%%% API
|
||||||
|
|
||||||
-spec checkout(ref()) ->
|
-spec checkout(ref()) -> snapshot() | no_return().
|
||||||
snapshot() | no_return().
|
|
||||||
|
|
||||||
checkout(Reference) ->
|
checkout(Reference) ->
|
||||||
checkout(Reference, undefined).
|
checkout(Reference, undefined).
|
||||||
|
|
||||||
-spec checkout(ref(), transport_opts()) ->
|
-spec checkout(ref(), transport_opts()) -> snapshot() | no_return().
|
||||||
snapshot() | no_return().
|
|
||||||
|
|
||||||
checkout(Reference, Opts) ->
|
checkout(Reference, Opts) ->
|
||||||
Version = ref_to_version(Reference),
|
Version = ref_to_version(Reference),
|
||||||
case dmt_client_cache:get(Version, Opts) of
|
case dmt_client_cache:get(Version, Opts) of
|
||||||
@ -70,15 +67,12 @@ checkout(Reference, Opts) ->
|
|||||||
erlang:error(Error)
|
erlang:error(Error)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec checkout_object(ref(), object_ref()) ->
|
-spec checkout_object(ref(), object_ref()) -> dmsl_domain_config_thrift:'VersionedObject'() | no_return().
|
||||||
dmsl_domain_config_thrift:'VersionedObject'() | no_return().
|
|
||||||
|
|
||||||
checkout_object(Reference, ObjectReference) ->
|
checkout_object(Reference, ObjectReference) ->
|
||||||
checkout_object(Reference, ObjectReference, undefined).
|
checkout_object(Reference, ObjectReference, undefined).
|
||||||
|
|
||||||
-spec checkout_object(ref(), object_ref(), transport_opts()) ->
|
-spec checkout_object(ref(), object_ref(), transport_opts()) ->
|
||||||
dmsl_domain_config_thrift:'VersionedObject'() | no_return().
|
dmsl_domain_config_thrift:'VersionedObject'() | no_return().
|
||||||
|
|
||||||
checkout_object(Reference, ObjectReference, Opts) ->
|
checkout_object(Reference, ObjectReference, Opts) ->
|
||||||
Version = ref_to_version(Reference),
|
Version = ref_to_version(Reference),
|
||||||
case dmt_client_cache:get_object(Version, ObjectReference, Opts) of
|
case dmt_client_cache:get_object(Version, ObjectReference, Opts) of
|
||||||
@ -90,41 +84,29 @@ checkout_object(Reference, ObjectReference, Opts) ->
|
|||||||
erlang:throw(#'ObjectNotFound'{})
|
erlang:throw(#'ObjectNotFound'{})
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec commit(version(), commit()) ->
|
-spec commit(version(), commit()) -> version() | no_return().
|
||||||
version() | no_return().
|
|
||||||
|
|
||||||
commit(Version, Commit) ->
|
commit(Version, Commit) ->
|
||||||
commit(Version, Commit, undefined).
|
commit(Version, Commit, undefined).
|
||||||
|
|
||||||
-spec commit(version(), commit(), transport_opts()) ->
|
-spec commit(version(), commit(), transport_opts()) -> version() | no_return().
|
||||||
version() | no_return().
|
|
||||||
|
|
||||||
commit(Version, Commit, Opts) ->
|
commit(Version, Commit, Opts) ->
|
||||||
dmt_client_backend:commit(Version, Commit, Opts).
|
dmt_client_backend:commit(Version, Commit, Opts).
|
||||||
|
|
||||||
-spec get_last_version() ->
|
-spec get_last_version() -> version().
|
||||||
version().
|
|
||||||
|
|
||||||
get_last_version() ->
|
get_last_version() ->
|
||||||
dmt_client_cache:get_last_version().
|
dmt_client_cache:get_last_version().
|
||||||
|
|
||||||
-spec pull_range(version(), limit()) ->
|
-spec pull_range(version(), limit()) -> history() | no_return().
|
||||||
history() | no_return().
|
|
||||||
|
|
||||||
pull_range(Version, Limit) ->
|
pull_range(Version, Limit) ->
|
||||||
pull_range(Version, Limit, undefined).
|
pull_range(Version, Limit, undefined).
|
||||||
|
|
||||||
-spec pull_range(version(), limit(), transport_opts()) ->
|
-spec pull_range(version(), limit(), transport_opts()) -> history() | no_return().
|
||||||
history() | no_return().
|
|
||||||
|
|
||||||
pull_range(Version, Limit, Opts) ->
|
pull_range(Version, Limit, Opts) ->
|
||||||
dmt_client_backend:pull_range(Version, Limit, Opts).
|
dmt_client_backend:pull_range(Version, Limit, Opts).
|
||||||
|
|
||||||
%% Health check API
|
%% Health check API
|
||||||
|
|
||||||
-spec health_check() ->
|
-spec health_check() -> erl_health:result().
|
||||||
erl_health:result().
|
|
||||||
|
|
||||||
health_check() ->
|
health_check() ->
|
||||||
try
|
try
|
||||||
_ = dmt_client_cache:get_last_version(),
|
_ = dmt_client_cache:get_last_version(),
|
||||||
@ -137,7 +119,6 @@ health_check() ->
|
|||||||
%%% Supervisor callbacks
|
%%% Supervisor callbacks
|
||||||
|
|
||||||
-spec init([]) -> {ok, {supervisor:sup_flags(), [supervisor:child_spec()]}}.
|
-spec init([]) -> {ok, {supervisor:sup_flags(), [supervisor:child_spec()]}}.
|
||||||
|
|
||||||
init([]) ->
|
init([]) ->
|
||||||
Cache = #{id => dmt_client_cache, start => {dmt_client_cache, start_link, []}, restart => permanent},
|
Cache = #{id => dmt_client_cache, start => {dmt_client_cache, start_link, []}, restart => permanent},
|
||||||
{ok, {#{strategy => one_for_one, intensity => 10, period => 60}, [Cache]}}.
|
{ok, {#{strategy => one_for_one, intensity => 10, period => 60}, [Cache]}}.
|
||||||
@ -145,20 +126,16 @@ init([]) ->
|
|||||||
%%% Application callbacks
|
%%% Application callbacks
|
||||||
|
|
||||||
-spec start(normal, any()) -> {ok, pid()} | {error, any()}.
|
-spec start(normal, any()) -> {ok, pid()} | {error, any()}.
|
||||||
|
|
||||||
start(_StartType, _StartArgs) ->
|
start(_StartType, _StartArgs) ->
|
||||||
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
|
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
|
||||||
|
|
||||||
-spec stop(any()) -> ok.
|
-spec stop(any()) -> ok.
|
||||||
|
|
||||||
stop(_State) ->
|
stop(_State) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
%%% Internal functions
|
%%% Internal functions
|
||||||
|
|
||||||
-spec ref_to_version(ref()) ->
|
-spec ref_to_version(ref()) -> version().
|
||||||
version().
|
|
||||||
|
|
||||||
ref_to_version({version, Version}) ->
|
ref_to_version({version, Version}) ->
|
||||||
Version;
|
Version;
|
||||||
ref_to_version({head, #'Head'{}}) ->
|
ref_to_version({head, #'Head'{}}) ->
|
||||||
|
@ -9,36 +9,30 @@
|
|||||||
|
|
||||||
-spec commit(dmt_client:version(), dmt_client:commit(), dmt_client:transport_opts()) ->
|
-spec commit(dmt_client:version(), dmt_client:commit(), dmt_client:transport_opts()) ->
|
||||||
dmt_client:version() | no_return().
|
dmt_client:version() | no_return().
|
||||||
|
|
||||||
commit(Version, Commit, Opts) ->
|
commit(Version, Commit, Opts) ->
|
||||||
call('Repository', 'Commit', {Version, Commit}, Opts).
|
call('Repository', 'Commit', {Version, Commit}, Opts).
|
||||||
|
|
||||||
-spec checkout(dmt_client:ref(), dmt_client:transport_opts()) ->
|
-spec checkout(dmt_client:ref(), dmt_client:transport_opts()) -> dmt_client:snapshot() | no_return().
|
||||||
dmt_client:snapshot() | no_return().
|
|
||||||
|
|
||||||
checkout(Reference, Opts) ->
|
checkout(Reference, Opts) ->
|
||||||
call('Repository', 'Checkout', {Reference}, Opts).
|
call('Repository', 'Checkout', {Reference}, Opts).
|
||||||
|
|
||||||
-spec pull_range(dmt_client:version(), dmt_client:limit(), dmt_client:transport_opts()) ->
|
-spec pull_range(dmt_client:version(), dmt_client:limit(), dmt_client:transport_opts()) ->
|
||||||
dmt_client:history() | no_return().
|
dmt_client:history() | no_return().
|
||||||
|
|
||||||
pull_range(After, Limit, Opts) ->
|
pull_range(After, Limit, Opts) ->
|
||||||
call('Repository', 'PullRange', {After, Limit}, Opts).
|
call('Repository', 'PullRange', {After, Limit}, Opts).
|
||||||
|
|
||||||
-spec checkout_object(dmt_client:ref(), dmt_client:object_ref(), dmt_client:transport_opts()) ->
|
-spec checkout_object(dmt_client:ref(), dmt_client:object_ref(), dmt_client:transport_opts()) ->
|
||||||
dmsl_domain_thrift:'DomainObject'() | no_return().
|
dmsl_domain_thrift:'DomainObject'() | no_return().
|
||||||
|
|
||||||
checkout_object(Reference, ObjectReference, Opts) ->
|
checkout_object(Reference, ObjectReference, Opts) ->
|
||||||
call('RepositoryClient', 'checkoutObject', {Reference, ObjectReference}, Opts).
|
call('RepositoryClient', 'checkoutObject', {Reference, ObjectReference}, Opts).
|
||||||
|
|
||||||
|
|
||||||
call(ServiceName, Function, Args, TransportOpts) ->
|
call(ServiceName, Function, Args, TransportOpts) ->
|
||||||
Url = get_service_url(ServiceName),
|
Url = get_service_url(ServiceName),
|
||||||
Service = get_service_modname(ServiceName),
|
Service = get_service_modname(ServiceName),
|
||||||
Call = {Service, Function, Args},
|
Call = {Service, Function, Args},
|
||||||
Opts = #{
|
Opts = #{
|
||||||
url => Url,
|
url => Url,
|
||||||
event_handler => get_event_handlers(),
|
event_handler => get_event_handlers(),
|
||||||
transport_opts => ensure_transport_opts(TransportOpts)
|
transport_opts => ensure_transport_opts(TransportOpts)
|
||||||
},
|
},
|
||||||
Context = woody_context:new(),
|
Context = woody_context:new(),
|
||||||
@ -63,9 +57,7 @@ get_service_module('RepositoryClient') ->
|
|||||||
get_event_handlers() ->
|
get_event_handlers() ->
|
||||||
genlib_app:env(dmt_client, woody_event_handlers, []).
|
genlib_app:env(dmt_client, woody_event_handlers, []).
|
||||||
|
|
||||||
-spec ensure_transport_opts(dmt_client:transport_opts()) ->
|
-spec ensure_transport_opts(dmt_client:transport_opts()) -> woody_client_thrift_http_transport:transport_options().
|
||||||
woody_client_thrift_http_transport:transport_options().
|
|
||||||
|
|
||||||
ensure_transport_opts(Opts) when is_map(Opts) ->
|
ensure_transport_opts(Opts) when is_map(Opts) ->
|
||||||
Opts;
|
Opts;
|
||||||
ensure_transport_opts(undefined) ->
|
ensure_transport_opts(undefined) ->
|
||||||
|
@ -10,8 +10,7 @@
|
|||||||
-callback commit(dmt_client:version(), dmt_client:commit(), dmt_client:transport_opts()) ->
|
-callback commit(dmt_client:version(), dmt_client:commit(), dmt_client:transport_opts()) ->
|
||||||
dmt_client:version() | no_return().
|
dmt_client:version() | no_return().
|
||||||
|
|
||||||
-callback checkout(dmt_client:ref(), dmt_client:transport_opts()) ->
|
-callback checkout(dmt_client:ref(), dmt_client:transport_opts()) -> dmt_client:snapshot() | no_return().
|
||||||
dmt_client:snapshot() | no_return().
|
|
||||||
|
|
||||||
-callback checkout_object(dmt_client:ref(), dmt_client:object_ref(), dmt_client:transport_opts()) ->
|
-callback checkout_object(dmt_client:ref(), dmt_client:object_ref(), dmt_client:transport_opts()) ->
|
||||||
dmsl_domain_thrift:'DomainObject'() | no_return().
|
dmsl_domain_thrift:'DomainObject'() | no_return().
|
||||||
@ -23,39 +22,30 @@
|
|||||||
|
|
||||||
-spec commit(dmt_client:version(), dmt_client:commit(), dmt_client:transport_opts()) ->
|
-spec commit(dmt_client:version(), dmt_client:commit(), dmt_client:transport_opts()) ->
|
||||||
dmt_client:version() | no_return().
|
dmt_client:version() | no_return().
|
||||||
|
|
||||||
commit(Version, Commit, Opts) ->
|
commit(Version, Commit, Opts) ->
|
||||||
call(commit, [Version, Commit, Opts]).
|
call(commit, [Version, Commit, Opts]).
|
||||||
|
|
||||||
-spec checkout(dmt_client:ref(), dmt_client:transport_opts()) ->
|
-spec checkout(dmt_client:ref(), dmt_client:transport_opts()) -> dmt_client:snapshot() | no_return().
|
||||||
dmt_client:snapshot() | no_return().
|
|
||||||
|
|
||||||
checkout(Reference, Opts) ->
|
checkout(Reference, Opts) ->
|
||||||
call(checkout, [Reference, Opts]).
|
call(checkout, [Reference, Opts]).
|
||||||
|
|
||||||
-spec checkout_object(dmt_client:ref(), dmt_client:object_ref(), dmt_client:transport_opts()) ->
|
-spec checkout_object(dmt_client:ref(), dmt_client:object_ref(), dmt_client:transport_opts()) ->
|
||||||
dmsl_domain_thrift:'DomainObject'() | no_return().
|
dmsl_domain_thrift:'DomainObject'() | no_return().
|
||||||
|
|
||||||
checkout_object(Reference, ObjectReference, Opts) ->
|
checkout_object(Reference, ObjectReference, Opts) ->
|
||||||
call(checkout_object, [Reference, ObjectReference, Opts]).
|
call(checkout_object, [Reference, ObjectReference, Opts]).
|
||||||
|
|
||||||
-spec pull_range(dmt_client:version(), dmt_client:limit(), dmt_client:transport_opts()) ->
|
-spec pull_range(dmt_client:version(), dmt_client:limit(), dmt_client:transport_opts()) ->
|
||||||
dmt_client:history() | no_return().
|
dmt_client:history() | no_return().
|
||||||
|
|
||||||
pull_range(After, Limit, Opts) ->
|
pull_range(After, Limit, Opts) ->
|
||||||
call(pull_range, [After, Limit, Opts]).
|
call(pull_range, [After, Limit, Opts]).
|
||||||
|
|
||||||
%%% Internal functions
|
%%% Internal functions
|
||||||
|
|
||||||
-spec get_api_module() ->
|
-spec get_api_module() -> module().
|
||||||
module().
|
|
||||||
|
|
||||||
get_api_module() ->
|
get_api_module() ->
|
||||||
genlib_app:env(dmt_client, api_module, dmt_client_api).
|
genlib_app:env(dmt_client, api_module, dmt_client_api).
|
||||||
|
|
||||||
-spec call(atom(), list()) ->
|
-spec call(atom(), list()) -> term() | no_return().
|
||||||
term() | no_return().
|
|
||||||
|
|
||||||
call(Fun, Args) ->
|
call(Fun, Args) ->
|
||||||
Module = get_api_module(),
|
Module = get_api_module(),
|
||||||
erlang:apply(Module, Fun, Args).
|
erlang:apply(Module, Fun, Args).
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
-module(dmt_client_cache).
|
-module(dmt_client_cache).
|
||||||
|
|
||||||
-behaviour(gen_server).
|
-behaviour(gen_server).
|
||||||
|
|
||||||
%% API
|
%% API
|
||||||
@ -80,21 +81,16 @@
|
|||||||
|
|
||||||
%%% API
|
%%% API
|
||||||
|
|
||||||
-spec start_link() ->
|
-spec start_link() -> {ok, pid()} | {error, {already_started, pid()}}.
|
||||||
{ok, pid()} | {error, {already_started, pid()}}.
|
|
||||||
|
|
||||||
start_link() ->
|
start_link() ->
|
||||||
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
|
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
|
||||||
|
|
||||||
-spec get(dmt_client:version()) ->
|
-spec get(dmt_client:version()) -> {ok, dmt_client:snapshot()} | {error, version_not_found | woody_error()}.
|
||||||
{ok, dmt_client:snapshot()} | {error, version_not_found | woody_error()}.
|
|
||||||
|
|
||||||
get(Version) ->
|
get(Version) ->
|
||||||
get(Version, undefined).
|
get(Version, undefined).
|
||||||
|
|
||||||
-spec get(dmt_client:version(), dmt_client:transport_opts()) ->
|
-spec get(dmt_client:version(), dmt_client:transport_opts()) ->
|
||||||
{ok, dmt_client:snapshot()} | {error, version_not_found | woody_error()}.
|
{ok, dmt_client:snapshot()} | {error, version_not_found | woody_error()}.
|
||||||
|
|
||||||
get(Version, Opts) ->
|
get(Version, Opts) ->
|
||||||
case get_snapshot(Version) of
|
case get_snapshot(Version) of
|
||||||
{ok, _Snapshot} = Result ->
|
{ok, _Snapshot} = Result ->
|
||||||
@ -105,13 +101,11 @@ get(Version, Opts) ->
|
|||||||
|
|
||||||
-spec get_object(dmt_client:version(), dmt_client:object_ref()) ->
|
-spec get_object(dmt_client:version(), dmt_client:object_ref()) ->
|
||||||
{ok, dmt_client:domain_object()} | {error, version_not_found | object_not_found | woody_error()}.
|
{ok, dmt_client:domain_object()} | {error, version_not_found | object_not_found | woody_error()}.
|
||||||
|
|
||||||
get_object(Version, ObjectRef) ->
|
get_object(Version, ObjectRef) ->
|
||||||
get_object(Version, ObjectRef, undefined).
|
get_object(Version, ObjectRef, undefined).
|
||||||
|
|
||||||
-spec get_object(dmt_client:version(), dmt_client:object_ref(), dmt_client:transport_opts()) ->
|
-spec get_object(dmt_client:version(), dmt_client:object_ref(), dmt_client:transport_opts()) ->
|
||||||
{ok, dmt_client:domain_object()} | {error, version_not_found | object_not_found | woody_error()}.
|
{ok, dmt_client:domain_object()} | {error, version_not_found | object_not_found | woody_error()}.
|
||||||
|
|
||||||
get_object(Version, ObjectRef, Opts) ->
|
get_object(Version, ObjectRef, Opts) ->
|
||||||
case do_get_object(Version, ObjectRef) of
|
case do_get_object(Version, ObjectRef) of
|
||||||
{ok, _Object} = Result ->
|
{ok, _Object} = Result ->
|
||||||
@ -122,9 +116,7 @@ get_object(Version, ObjectRef, Opts) ->
|
|||||||
NotFound
|
NotFound
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec get_last_version() ->
|
-spec get_last_version() -> dmt_client:version() | no_return().
|
||||||
dmt_client:version() | no_return().
|
|
||||||
|
|
||||||
get_last_version() ->
|
get_last_version() ->
|
||||||
case do_get_last_version() of
|
case do_get_last_version() of
|
||||||
{ok, Version} ->
|
{ok, Version} ->
|
||||||
@ -138,24 +130,18 @@ get_last_version() ->
|
|||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec update() ->
|
-spec update() -> {ok, dmt_client:version()} | {error, woody_error()}.
|
||||||
{ok, dmt_client:version()} | {error, woody_error()}.
|
|
||||||
|
|
||||||
update() ->
|
update() ->
|
||||||
call(update).
|
call(update).
|
||||||
|
|
||||||
%%% gen_server callbacks
|
%%% gen_server callbacks
|
||||||
|
|
||||||
-spec init(_) ->
|
-spec init(_) -> {ok, state(), 0}.
|
||||||
{ok, state(), 0}.
|
|
||||||
|
|
||||||
init(_) ->
|
init(_) ->
|
||||||
ok = create_tables(),
|
ok = create_tables(),
|
||||||
{ok, #state{}, 0}.
|
{ok, #state{}, 0}.
|
||||||
|
|
||||||
-spec handle_call(term(), {pid(), term()}, state()) ->
|
-spec handle_call(term(), {pid(), term()}, state()) -> {reply, term(), state()}.
|
||||||
{reply, term(), state()}.
|
|
||||||
|
|
||||||
handle_call({get_object, Version, ObjectRef, Opts}, From, #state{waiters = Waiters} = State) ->
|
handle_call({get_object, Version, ObjectRef, Opts}, From, #state{waiters = Waiters} = State) ->
|
||||||
case do_get_object(Version, ObjectRef) of
|
case do_get_object(Version, ObjectRef) of
|
||||||
{ok, _Object} = Result ->
|
{ok, _Object} = Result ->
|
||||||
@ -164,29 +150,24 @@ handle_call({get_object, Version, ObjectRef, Opts}, From, #state{waiters = Waite
|
|||||||
{reply, NotFound, State};
|
{reply, NotFound, State};
|
||||||
{error, version_not_found} ->
|
{error, version_not_found} ->
|
||||||
DispatchFun = dispatch_object(ObjectRef),
|
DispatchFun = dispatch_object(ObjectRef),
|
||||||
NewWaiters = maybe_fetch({version, Version}, From, DispatchFun, Waiters, Opts),
|
NewWaiters = maybe_fetch({version, Version}, From, DispatchFun, Waiters, Opts),
|
||||||
{noreply, State#state{waiters = NewWaiters}}
|
{noreply, State#state{waiters = NewWaiters}}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
handle_call(update, From, State) ->
|
handle_call(update, From, State) ->
|
||||||
update_cache(From, State);
|
update_cache(From, State);
|
||||||
|
|
||||||
handle_call({get_snapshot, Version, Opts}, From, #state{waiters = Waiters} = State) ->
|
handle_call({get_snapshot, Version, Opts}, From, #state{waiters = Waiters} = State) ->
|
||||||
case get_snapshot(Version) of
|
case get_snapshot(Version) of
|
||||||
{ok, _Snapshot} = Result ->
|
{ok, _Snapshot} = Result ->
|
||||||
{reply, Result, State};
|
{reply, Result, State};
|
||||||
{error, version_not_found} ->
|
{error, version_not_found} ->
|
||||||
DispatchFun = fun dispatch_snapshot/2,
|
DispatchFun = fun dispatch_snapshot/2,
|
||||||
NewWaiters = maybe_fetch({version, Version}, From, DispatchFun, Waiters, Opts),
|
NewWaiters = maybe_fetch({version, Version}, From, DispatchFun, Waiters, Opts),
|
||||||
{noreply, State#state{waiters = NewWaiters}}
|
{noreply, State#state{waiters = NewWaiters}}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
handle_call(_Msg, _From, State) ->
|
handle_call(_Msg, _From, State) ->
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
-spec handle_cast(term(), state()) ->
|
-spec handle_cast(term(), state()) -> {noreply, state()}.
|
||||||
{noreply, state()}.
|
|
||||||
|
|
||||||
handle_cast({dispatch, Reference, Result}, #state{waiters = Waiters} = State) ->
|
handle_cast({dispatch, Reference, Result}, #state{waiters = Waiters} = State) ->
|
||||||
case Result of
|
case Result of
|
||||||
{ok, Snapshot} ->
|
{ok, Snapshot} ->
|
||||||
@ -196,50 +177,36 @@ handle_cast({dispatch, Reference, Result}, #state{waiters = Waiters} = State) ->
|
|||||||
end,
|
end,
|
||||||
_ = [DispatchFun(From, Result) || {From, DispatchFun} <- maps:get(Reference, Waiters, [])],
|
_ = [DispatchFun(From, Result) || {From, DispatchFun} <- maps:get(Reference, Waiters, [])],
|
||||||
{noreply, State#state{waiters = maps:remove(Reference, Waiters)}};
|
{noreply, State#state{waiters = maps:remove(Reference, Waiters)}};
|
||||||
|
|
||||||
handle_cast(_Msg, State) ->
|
handle_cast(_Msg, State) ->
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
-spec handle_info(term(), state()) ->
|
-spec handle_info(term(), state()) -> {noreply, state()}.
|
||||||
{noreply, state()}.
|
|
||||||
|
|
||||||
handle_info(timeout, State) ->
|
handle_info(timeout, State) ->
|
||||||
update_cache(undefined, State);
|
update_cache(undefined, State);
|
||||||
|
|
||||||
handle_info(_Msg, State) ->
|
handle_info(_Msg, State) ->
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
-spec terminate(term(), state()) ->
|
-spec terminate(term(), state()) -> ok.
|
||||||
ok.
|
|
||||||
|
|
||||||
terminate(_Reason, _State) ->
|
terminate(_Reason, _State) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
-spec code_change(term(), state(), term()) ->
|
-spec code_change(term(), state(), term()) -> {ok, state()}.
|
||||||
{ok, state()}.
|
|
||||||
|
|
||||||
code_change(_OldVsn, State, _Extra) ->
|
code_change(_OldVsn, State, _Extra) ->
|
||||||
{ok, State}.
|
{ok, State}.
|
||||||
|
|
||||||
%%% Internal functions
|
%%% Internal functions
|
||||||
|
|
||||||
-spec create_tables() ->
|
-spec create_tables() -> ok.
|
||||||
ok.
|
|
||||||
|
|
||||||
create_tables() ->
|
create_tables() ->
|
||||||
?TABLE = ets:new(?TABLE, ?meta_table_opts),
|
?TABLE = ets:new(?TABLE, ?meta_table_opts),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
-spec call(term()) ->
|
-spec call(term()) -> term().
|
||||||
term().
|
|
||||||
|
|
||||||
call(Msg) ->
|
call(Msg) ->
|
||||||
DefTimeout = application:get_env(dmt_client, cache_server_call_timeout, ?DEFAULT_CALL_TIMEOUT),
|
DefTimeout = application:get_env(dmt_client, cache_server_call_timeout, ?DEFAULT_CALL_TIMEOUT),
|
||||||
call(Msg, DefTimeout).
|
call(Msg, DefTimeout).
|
||||||
|
|
||||||
-spec call(term(), timeout()) ->
|
-spec call(term(), timeout()) -> term().
|
||||||
term().
|
|
||||||
|
|
||||||
call(Msg, Timeout) ->
|
call(Msg, Timeout) ->
|
||||||
try
|
try
|
||||||
gen_server:call(?SERVER, Msg, Timeout)
|
gen_server:call(?SERVER, Msg, Timeout)
|
||||||
@ -248,21 +215,17 @@ call(Msg, Timeout) ->
|
|||||||
woody_error:raise(system, {external, resource_unavailable, <<"dmt_client_cache timeout">>})
|
woody_error:raise(system, {external, resource_unavailable, <<"dmt_client_cache timeout">>})
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec cast(term()) ->
|
-spec cast(term()) -> ok.
|
||||||
ok.
|
|
||||||
|
|
||||||
cast(Msg) ->
|
cast(Msg) ->
|
||||||
gen_server:cast(?SERVER, Msg).
|
gen_server:cast(?SERVER, Msg).
|
||||||
|
|
||||||
-spec put_snapshot(dmt_client:snapshot()) ->
|
-spec put_snapshot(dmt_client:snapshot()) -> ok.
|
||||||
ok.
|
|
||||||
|
|
||||||
put_snapshot(#'Snapshot'{version = Version, domain = Domain}) ->
|
put_snapshot(#'Snapshot'{version = Version, domain = Domain}) ->
|
||||||
case get_snap(Version) of
|
case get_snap(Version) of
|
||||||
{ok, _Snap} ->
|
{ok, _Snap} ->
|
||||||
ok;
|
ok;
|
||||||
{error, version_not_found} ->
|
{error, version_not_found} ->
|
||||||
TID = ets:new(?MODULE, ?snapshot_table_opts),
|
TID = ets:new(?MODULE, ?snapshot_table_opts),
|
||||||
true = put_domain_to_table(TID, Domain),
|
true = put_domain_to_table(TID, Domain),
|
||||||
Snap = #snap{
|
Snap = #snap{
|
||||||
vsn = Version,
|
vsn = Version,
|
||||||
@ -273,9 +236,7 @@ put_snapshot(#'Snapshot'{version = Version, domain = Domain}) ->
|
|||||||
cleanup()
|
cleanup()
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec put_domain_to_table(ets:tid(), dmt_client:domain()) ->
|
-spec put_domain_to_table(ets:tid(), dmt_client:domain()) -> true.
|
||||||
true.
|
|
||||||
|
|
||||||
put_domain_to_table(TID, Domain) ->
|
put_domain_to_table(TID, Domain) ->
|
||||||
dmt_domain:fold(
|
dmt_domain:fold(
|
||||||
fun(Ref, Object, _) ->
|
fun(Ref, Object, _) ->
|
||||||
@ -285,9 +246,7 @@ put_domain_to_table(TID, Domain) ->
|
|||||||
Domain
|
Domain
|
||||||
).
|
).
|
||||||
|
|
||||||
-spec get_snapshot(dmt_client:version()) ->
|
-spec get_snapshot(dmt_client:version()) -> {ok, dmt_client:snapshot()} | {error, version_not_found}.
|
||||||
{ok, dmt_client:snapshot()} | {error, version_not_found}.
|
|
||||||
|
|
||||||
get_snapshot(Version) ->
|
get_snapshot(Version) ->
|
||||||
case get_snap(Version) of
|
case get_snap(Version) of
|
||||||
{ok, Snap} ->
|
{ok, Snap} ->
|
||||||
@ -296,9 +255,7 @@ get_snapshot(Version) ->
|
|||||||
Error
|
Error
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec get_snap(dmt_client:version()) ->
|
-spec get_snap(dmt_client:version()) -> {ok, snap()} | {error, version_not_found}.
|
||||||
{ok, snap()} | {error, version_not_found}.
|
|
||||||
|
|
||||||
get_snap(Version) ->
|
get_snap(Version) ->
|
||||||
case ets:lookup(?TABLE, Version) of
|
case ets:lookup(?TABLE, Version) of
|
||||||
[Snap] ->
|
[Snap] ->
|
||||||
@ -308,15 +265,12 @@ get_snap(Version) ->
|
|||||||
{error, version_not_found}
|
{error, version_not_found}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec get_all_snaps() ->
|
-spec get_all_snaps() -> [snap()].
|
||||||
[snap()].
|
|
||||||
|
|
||||||
get_all_snaps() ->
|
get_all_snaps() ->
|
||||||
ets:tab2list(?TABLE).
|
ets:tab2list(?TABLE).
|
||||||
|
|
||||||
-spec do_get_object(dmt_client:version(), dmt_client:object_ref()) ->
|
-spec do_get_object(dmt_client:version(), dmt_client:object_ref()) ->
|
||||||
{ok, dmt_client:domain_object()} | {error, version_not_found | object_not_found}.
|
{ok, dmt_client:domain_object()} | {error, version_not_found | object_not_found}.
|
||||||
|
|
||||||
do_get_object(Version, ObjectRef) ->
|
do_get_object(Version, ObjectRef) ->
|
||||||
case get_snap(Version) of
|
case get_snap(Version) of
|
||||||
{ok, Snap} ->
|
{ok, Snap} ->
|
||||||
@ -327,7 +281,6 @@ do_get_object(Version, ObjectRef) ->
|
|||||||
|
|
||||||
-spec get_object_by_snap(snap(), dmt_client:object_ref()) ->
|
-spec get_object_by_snap(snap(), dmt_client:object_ref()) ->
|
||||||
{ok, dmt_client:domain_object()} | {error, version_not_found | object_not_found}.
|
{ok, dmt_client:domain_object()} | {error, version_not_found | object_not_found}.
|
||||||
|
|
||||||
get_object_by_snap(#snap{tid = TID}, ObjectRef) ->
|
get_object_by_snap(#snap{tid = TID}, ObjectRef) ->
|
||||||
try ets:lookup(TID, ObjectRef) of
|
try ets:lookup(TID, ObjectRef) of
|
||||||
[#object{obj = Object}] ->
|
[#object{obj = Object}] ->
|
||||||
@ -335,13 +288,13 @@ get_object_by_snap(#snap{tid = TID}, ObjectRef) ->
|
|||||||
[] ->
|
[] ->
|
||||||
{error, object_not_found}
|
{error, object_not_found}
|
||||||
catch
|
catch
|
||||||
error:badarg -> % table was deleted
|
% table was deleted
|
||||||
|
error:badarg ->
|
||||||
{error, version_not_found}
|
{error, version_not_found}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec get_object_from_snapshot(dmt_client:object_ref(), dmt_client:snapshot()) ->
|
-spec get_object_from_snapshot(dmt_client:object_ref(), dmt_client:snapshot()) ->
|
||||||
{ok, dmt_client:domain_object()} | {error, object_not_found}.
|
{ok, dmt_client:domain_object()} | {error, object_not_found}.
|
||||||
|
|
||||||
get_object_from_snapshot(ObjectRef, #'Snapshot'{domain = Domain}) ->
|
get_object_from_snapshot(ObjectRef, #'Snapshot'{domain = Domain}) ->
|
||||||
case dmt_domain:get_object(ObjectRef, Domain) of
|
case dmt_domain:get_object(ObjectRef, Domain) of
|
||||||
{ok, _Object} = Result ->
|
{ok, _Object} = Result ->
|
||||||
@ -350,17 +303,14 @@ get_object_from_snapshot(ObjectRef, #'Snapshot'{domain = Domain}) ->
|
|||||||
{error, object_not_found}
|
{error, object_not_found}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec update_cache(from() | undefined, state()) ->
|
-spec update_cache(from() | undefined, state()) -> {noreply, state()}.
|
||||||
{noreply, state()}.
|
|
||||||
|
|
||||||
update_cache(From, #state{waiters = Waiters} = State) ->
|
update_cache(From, #state{waiters = Waiters} = State) ->
|
||||||
DispatchFun = fun dispatch_update/2,
|
DispatchFun = fun dispatch_update/2,
|
||||||
NewWaiters = maybe_fetch({head, #'Head'{}}, From, DispatchFun, Waiters, undefined),
|
NewWaiters = maybe_fetch({head, #'Head'{}}, From, DispatchFun, Waiters, undefined),
|
||||||
{noreply, restart_timer(State#state{waiters = NewWaiters})}.
|
{noreply, restart_timer(State#state{waiters = NewWaiters})}.
|
||||||
|
|
||||||
-spec maybe_fetch(dmt_client:ref(), from() | undefined, dispatch_fun(), waiters(), dmt_client:transport_opts()) ->
|
-spec maybe_fetch(dmt_client:ref(), from() | undefined, dispatch_fun(), waiters(), dmt_client:transport_opts()) ->
|
||||||
waiters().
|
waiters().
|
||||||
|
|
||||||
maybe_fetch(Reference, From, DispatchFun, Waiters, Opts) ->
|
maybe_fetch(Reference, From, DispatchFun, Waiters, Opts) ->
|
||||||
Prev =
|
Prev =
|
||||||
case maps:find(Reference, Waiters) of
|
case maps:find(Reference, Waiters) of
|
||||||
@ -372,9 +322,7 @@ maybe_fetch(Reference, From, DispatchFun, Waiters, Opts) ->
|
|||||||
end,
|
end,
|
||||||
Waiters#{Reference => [{From, DispatchFun} | Prev]}.
|
Waiters#{Reference => [{From, DispatchFun} | Prev]}.
|
||||||
|
|
||||||
-spec schedule_fetch(dmt_client:ref(), dmt_client:transport_opts()) ->
|
-spec schedule_fetch(dmt_client:ref(), dmt_client:transport_opts()) -> pid().
|
||||||
pid().
|
|
||||||
|
|
||||||
schedule_fetch(Reference, Opts) ->
|
schedule_fetch(Reference, Opts) ->
|
||||||
proc_lib:spawn_link(
|
proc_lib:spawn_link(
|
||||||
fun() ->
|
fun() ->
|
||||||
@ -383,9 +331,7 @@ schedule_fetch(Reference, Opts) ->
|
|||||||
end
|
end
|
||||||
).
|
).
|
||||||
|
|
||||||
-spec fetch(dmt_client:ref(), dmt_client:transport_opts()) ->
|
-spec fetch(dmt_client:ref(), dmt_client:transport_opts()) -> fetch_result().
|
||||||
fetch_result().
|
|
||||||
|
|
||||||
fetch(Reference, Opts) ->
|
fetch(Reference, Opts) ->
|
||||||
try
|
try
|
||||||
Snapshot = do_fetch(Reference, Opts),
|
Snapshot = do_fetch(Reference, Opts),
|
||||||
@ -397,9 +343,7 @@ fetch(Reference, Opts) ->
|
|||||||
{error, Error}
|
{error, Error}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec do_fetch(dmt_client:ref(), dmt_client:transport_opts()) ->
|
-spec do_fetch(dmt_client:ref(), dmt_client:transport_opts()) -> dmt_client:snapshot() | no_return().
|
||||||
dmt_client:snapshot() | no_return().
|
|
||||||
|
|
||||||
do_fetch({head, #'Head'{}}, Opts) ->
|
do_fetch({head, #'Head'{}}, Opts) ->
|
||||||
case latest_snapshot() of
|
case latest_snapshot() of
|
||||||
{ok, OldHead} ->
|
{ok, OldHead} ->
|
||||||
@ -413,18 +357,14 @@ do_fetch({head, #'Head'{}}, Opts) ->
|
|||||||
do_fetch(Reference, Opts) ->
|
do_fetch(Reference, Opts) ->
|
||||||
dmt_client_backend:checkout(Reference, Opts).
|
dmt_client_backend:checkout(Reference, Opts).
|
||||||
|
|
||||||
-spec dispatch_snapshot(from() | undefined, fetch_result()) ->
|
-spec dispatch_snapshot(from() | undefined, fetch_result()) -> ok.
|
||||||
ok.
|
|
||||||
|
|
||||||
dispatch_snapshot(undefined, _Result) ->
|
dispatch_snapshot(undefined, _Result) ->
|
||||||
ok;
|
ok;
|
||||||
dispatch_snapshot(From, Result) ->
|
dispatch_snapshot(From, Result) ->
|
||||||
_ = gen_server:reply(From, Result),
|
_ = gen_server:reply(From, Result),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
-spec dispatch_object(dmt_client:object_ref()) ->
|
-spec dispatch_object(dmt_client:object_ref()) -> dispatch_fun().
|
||||||
dispatch_fun().
|
|
||||||
|
|
||||||
dispatch_object(ObjectRef) ->
|
dispatch_object(ObjectRef) ->
|
||||||
fun(From, Result) ->
|
fun(From, Result) ->
|
||||||
Reply =
|
Reply =
|
||||||
@ -437,9 +377,7 @@ dispatch_object(ObjectRef) ->
|
|||||||
gen_server:reply(From, Reply)
|
gen_server:reply(From, Reply)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec dispatch_update(from() | undefined, fetch_result()) ->
|
-spec dispatch_update(from() | undefined, fetch_result()) -> ok.
|
||||||
ok.
|
|
||||||
|
|
||||||
dispatch_update(undefined, _Result) ->
|
dispatch_update(undefined, _Result) ->
|
||||||
ok;
|
ok;
|
||||||
dispatch_update(From, {ok, #'Snapshot'{version = Version}}) ->
|
dispatch_update(From, {ok, #'Snapshot'{version = Version}}) ->
|
||||||
@ -449,9 +387,7 @@ dispatch_update(From, Error) ->
|
|||||||
_ = gen_server:reply(From, Error),
|
_ = gen_server:reply(From, Error),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
-spec do_get_snapshot(snap()) ->
|
-spec do_get_snapshot(snap()) -> {ok, dmt_client:snapshot()} | {error, version_not_found}.
|
||||||
{ok, dmt_client:snapshot()} | {error, version_not_found}.
|
|
||||||
|
|
||||||
do_get_snapshot(#snap{vsn = Version, tid = TID}) ->
|
do_get_snapshot(#snap{vsn = Version, tid = TID}) ->
|
||||||
try
|
try
|
||||||
Domain = ets:foldl(
|
Domain = ets:foldl(
|
||||||
@ -464,13 +400,12 @@ do_get_snapshot(#snap{vsn = Version, tid = TID}) ->
|
|||||||
),
|
),
|
||||||
{ok, #'Snapshot'{version = Version, domain = Domain}}
|
{ok, #'Snapshot'{version = Version, domain = Domain}}
|
||||||
catch
|
catch
|
||||||
error:badarg -> % table was deleted due to cleanup process or crash
|
% table was deleted due to cleanup process or crash
|
||||||
|
error:badarg ->
|
||||||
{error, version_not_found}
|
{error, version_not_found}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec latest_snapshot() ->
|
-spec latest_snapshot() -> {ok, dmt_client:snapshot()} | {error, version_not_found}.
|
||||||
{ok, dmt_client:snapshot()} | {error, version_not_found}.
|
|
||||||
|
|
||||||
latest_snapshot() ->
|
latest_snapshot() ->
|
||||||
case do_get_last_version() of
|
case do_get_last_version() of
|
||||||
{ok, Version} ->
|
{ok, Version} ->
|
||||||
@ -479,9 +414,7 @@ latest_snapshot() ->
|
|||||||
Error
|
Error
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec do_get_last_version() ->
|
-spec do_get_last_version() -> {ok, dmt_client:version()} | {error, version_not_found}.
|
||||||
{ok, dmt_client:version()} | {error, version_not_found}.
|
|
||||||
|
|
||||||
do_get_last_version() ->
|
do_get_last_version() ->
|
||||||
case ets:last(?TABLE) of
|
case ets:last(?TABLE) of
|
||||||
'$end_of_table' ->
|
'$end_of_table' ->
|
||||||
@ -490,42 +423,34 @@ do_get_last_version() ->
|
|||||||
{ok, Version}
|
{ok, Version}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec restart_timer(state()) ->
|
-spec restart_timer(state()) -> state().
|
||||||
state().
|
|
||||||
|
|
||||||
restart_timer(State = #state{timer = undefined}) ->
|
restart_timer(State = #state{timer = undefined}) ->
|
||||||
start_timer(State);
|
start_timer(State);
|
||||||
|
|
||||||
restart_timer(State = #state{timer = TimerRef}) ->
|
restart_timer(State = #state{timer = TimerRef}) ->
|
||||||
_ = erlang:cancel_timer(TimerRef),
|
_ = erlang:cancel_timer(TimerRef),
|
||||||
start_timer(State#state{timer = undefined}).
|
start_timer(State#state{timer = undefined}).
|
||||||
|
|
||||||
-spec start_timer(state()) ->
|
-spec start_timer(state()) -> state().
|
||||||
state().
|
|
||||||
|
|
||||||
start_timer(State = #state{timer = undefined}) ->
|
start_timer(State = #state{timer = undefined}) ->
|
||||||
Interval = genlib_app:env(dmt_client, cache_update_interval, ?DEFAULT_INTERVAL),
|
Interval = genlib_app:env(dmt_client, cache_update_interval, ?DEFAULT_INTERVAL),
|
||||||
State#state{timer = erlang:send_after(Interval, self(), timeout)}.
|
State#state{timer = erlang:send_after(Interval, self(), timeout)}.
|
||||||
|
|
||||||
-spec cleanup() ->
|
-spec cleanup() -> ok.
|
||||||
ok.
|
|
||||||
|
|
||||||
cleanup() ->
|
cleanup() ->
|
||||||
Snaps = get_all_snaps(),
|
Snaps = get_all_snaps(),
|
||||||
Sorted = lists:keysort(#snap.last_access, Snaps),
|
Sorted = lists:keysort(#snap.last_access, Snaps),
|
||||||
{ok, HeadVersion} = do_get_last_version(),
|
{ok, HeadVersion} = do_get_last_version(),
|
||||||
cleanup(Sorted, HeadVersion).
|
cleanup(Sorted, HeadVersion).
|
||||||
|
|
||||||
-spec cleanup([snap()], dmt_client:version()) ->
|
-spec cleanup([snap()], dmt_client:version()) -> ok.
|
||||||
ok.
|
|
||||||
|
|
||||||
cleanup([], _HeadVersion) ->
|
cleanup([], _HeadVersion) ->
|
||||||
ok;
|
ok;
|
||||||
cleanup(Snaps, HeadVersion) ->
|
cleanup(Snaps, HeadVersion) ->
|
||||||
{Elements, Memory} = get_cache_size(),
|
{Elements, Memory} = get_cache_size(),
|
||||||
CacheLimits = genlib_app:env(dmt_client, max_cache_size),
|
CacheLimits = genlib_app:env(dmt_client, max_cache_size),
|
||||||
MaxElements = genlib_map:get(elements, CacheLimits, 20),
|
MaxElements = genlib_map:get(elements, CacheLimits, 20),
|
||||||
MaxMemory = genlib_map:get(memory, CacheLimits, 52428800), % 50Mb by default
|
% 50Mb by default
|
||||||
|
MaxMemory = genlib_map:get(memory, CacheLimits, 52428800),
|
||||||
case Elements > MaxElements orelse (Elements > 1 andalso Memory > MaxMemory) of
|
case Elements > MaxElements orelse (Elements > 1 andalso Memory > MaxMemory) of
|
||||||
true ->
|
true ->
|
||||||
Tail = remove_earliest(Snaps, HeadVersion),
|
Tail = remove_earliest(Snaps, HeadVersion),
|
||||||
@ -534,18 +459,14 @@ cleanup(Snaps, HeadVersion) ->
|
|||||||
ok
|
ok
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec get_cache_size() ->
|
-spec get_cache_size() -> {non_neg_integer(), non_neg_integer()}.
|
||||||
{non_neg_integer(), non_neg_integer()}.
|
|
||||||
|
|
||||||
get_cache_size() ->
|
get_cache_size() ->
|
||||||
WordSize = erlang:system_info(wordsize),
|
WordSize = erlang:system_info(wordsize),
|
||||||
Info = ets:info(?TABLE),
|
Info = ets:info(?TABLE),
|
||||||
Words = get_snapshot_tables_size(),
|
Words = get_snapshot_tables_size(),
|
||||||
{proplists:get_value(size, Info), WordSize * Words}.
|
{proplists:get_value(size, Info), WordSize * Words}.
|
||||||
|
|
||||||
-spec get_snapshot_tables_size() ->
|
-spec get_snapshot_tables_size() -> non_neg_integer().
|
||||||
non_neg_integer().
|
|
||||||
|
|
||||||
get_snapshot_tables_size() ->
|
get_snapshot_tables_size() ->
|
||||||
ets:foldl(
|
ets:foldl(
|
||||||
fun(#snap{tid = TID}, Words) ->
|
fun(#snap{tid = TID}, Words) ->
|
||||||
@ -555,39 +476,29 @@ get_snapshot_tables_size() ->
|
|||||||
?TABLE
|
?TABLE
|
||||||
).
|
).
|
||||||
|
|
||||||
-spec ets_memory(ets:tid()) ->
|
-spec ets_memory(ets:tid()) -> non_neg_integer().
|
||||||
non_neg_integer().
|
|
||||||
|
|
||||||
ets_memory(TID) ->
|
ets_memory(TID) ->
|
||||||
Info = ets:info(TID),
|
Info = ets:info(TID),
|
||||||
proplists:get_value(memory, Info).
|
proplists:get_value(memory, Info).
|
||||||
|
|
||||||
-spec remove_earliest([snap()], dmt_client:version()) ->
|
-spec remove_earliest([snap()], dmt_client:version()) -> [snap()].
|
||||||
[snap()].
|
|
||||||
|
|
||||||
remove_earliest([#snap{vsn = HeadVersion} | Tail], HeadVersion) ->
|
remove_earliest([#snap{vsn = HeadVersion} | Tail], HeadVersion) ->
|
||||||
Tail;
|
Tail;
|
||||||
remove_earliest([Snap | Tail], _HeadVersion) ->
|
remove_earliest([Snap | Tail], _HeadVersion) ->
|
||||||
remove_snap(Snap),
|
remove_snap(Snap),
|
||||||
Tail.
|
Tail.
|
||||||
|
|
||||||
-spec remove_snap(snap()) ->
|
-spec remove_snap(snap()) -> ok.
|
||||||
ok.
|
|
||||||
|
|
||||||
remove_snap(#snap{tid = TID, vsn = Version}) ->
|
remove_snap(#snap{tid = TID, vsn = Version}) ->
|
||||||
true = ets:delete(?TABLE, Version),
|
true = ets:delete(?TABLE, Version),
|
||||||
true = ets:delete(TID),
|
true = ets:delete(TID),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
-spec update_last_access(dmt_client:version()) ->
|
-spec update_last_access(dmt_client:version()) -> boolean().
|
||||||
boolean().
|
|
||||||
|
|
||||||
update_last_access(Version) ->
|
update_last_access(Version) ->
|
||||||
ets:update_element(?TABLE, Version, {#snap.last_access, timestamp()}).
|
ets:update_element(?TABLE, Version, {#snap.last_access, timestamp()}).
|
||||||
|
|
||||||
-spec timestamp() ->
|
-spec timestamp() -> timestamp().
|
||||||
timestamp().
|
|
||||||
|
|
||||||
timestamp() ->
|
timestamp() ->
|
||||||
erlang:monotonic_time(microsecond).
|
erlang:monotonic_time(microsecond).
|
||||||
|
|
||||||
@ -595,14 +506,12 @@ timestamp() ->
|
|||||||
|
|
||||||
-ifdef(TEST).
|
-ifdef(TEST).
|
||||||
|
|
||||||
-spec test() -> % dirty hack for warn_missing_spec
|
% dirty hack for warn_missing_spec
|
||||||
any().
|
-spec test() -> any().
|
||||||
|
|
||||||
-include_lib("eunit/include/eunit.hrl").
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
|
|
||||||
-spec cleanup_test() ->
|
-spec cleanup_test() -> ok.
|
||||||
ok.
|
|
||||||
|
|
||||||
cleanup_test() ->
|
cleanup_test() ->
|
||||||
application:set_env(dmt_client, max_cache_size, #{elements => 2, memory => 52428800}),
|
application:set_env(dmt_client, max_cache_size, #{elements => 2, memory => 52428800}),
|
||||||
ok = create_tables(),
|
ok = create_tables(),
|
||||||
@ -619,9 +528,7 @@ cleanup_test() ->
|
|||||||
] = get_all_snaps(),
|
] = get_all_snaps(),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
-spec last_access_test() ->
|
-spec last_access_test() -> ok.
|
||||||
ok.
|
|
||||||
|
|
||||||
last_access_test() ->
|
last_access_test() ->
|
||||||
application:set_env(dmt_client, max_cache_size, #{elements => 3, memory => 52428800}),
|
application:set_env(dmt_client, max_cache_size, #{elements => 3, memory => 52428800}),
|
||||||
% Tables already created in cleanup_test/0
|
% Tables already created in cleanup_test/0
|
||||||
@ -641,4 +548,5 @@ last_access_test() ->
|
|||||||
] = get_all_snaps(),
|
] = get_all_snaps(),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
-endif. % TEST
|
% TEST
|
||||||
|
-endif.
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
-module(dmt_client_cache_SUITE).
|
-module(dmt_client_cache_SUITE).
|
||||||
|
|
||||||
-include_lib("common_test/include/ct.hrl").
|
-include_lib("common_test/include/ct.hrl").
|
||||||
|
|
||||||
-export([all/0]).
|
-export([all/0]).
|
||||||
@ -31,17 +32,13 @@
|
|||||||
|
|
||||||
%%% Common test callbacks
|
%%% Common test callbacks
|
||||||
|
|
||||||
-spec all() ->
|
-spec all() -> [testcase_or_group()].
|
||||||
[testcase_or_group()].
|
|
||||||
|
|
||||||
all() ->
|
all() ->
|
||||||
[
|
[
|
||||||
{group, main}
|
{group, main}
|
||||||
].
|
].
|
||||||
|
|
||||||
-spec groups() ->
|
-spec groups() -> [{atom(), list(), [testcase_or_group()]}].
|
||||||
[{atom(), list(), [testcase_or_group()]}].
|
|
||||||
|
|
||||||
groups() ->
|
groups() ->
|
||||||
[
|
[
|
||||||
{main, [parallel, shuffle], [
|
{main, [parallel, shuffle], [
|
||||||
@ -57,33 +54,30 @@ groups() ->
|
|||||||
{object_not_found, [parallel], lists:duplicate(?tests_count, object_not_found)},
|
{object_not_found, [parallel], lists:duplicate(?tests_count, object_not_found)},
|
||||||
{mixed, [parallel, shuffle],
|
{mixed, [parallel, shuffle],
|
||||||
lists:duplicate(?tests_count, get_snapshot_success) ++
|
lists:duplicate(?tests_count, get_snapshot_success) ++
|
||||||
lists:duplicate(?tests_count, snapshot_not_found) ++
|
lists:duplicate(?tests_count, snapshot_not_found) ++
|
||||||
lists:duplicate(?tests_count, woody_error) ++
|
lists:duplicate(?tests_count, woody_error) ++
|
||||||
lists:duplicate(?tests_count, object_not_found)
|
lists:duplicate(?tests_count, object_not_found)}
|
||||||
}
|
|
||||||
].
|
].
|
||||||
|
|
||||||
-spec init_per_suite(config()) ->
|
-spec init_per_suite(config()) -> config().
|
||||||
config().
|
|
||||||
|
|
||||||
init_per_suite(C) ->
|
init_per_suite(C) ->
|
||||||
Apps = genlib_app:start_application_with(dmt_client, [
|
Apps = genlib_app:start_application_with(dmt_client, [
|
||||||
{api_module, ?MODULE},
|
{api_module, ?MODULE},
|
||||||
{cache_update_interval, 5000}, % milliseconds
|
% milliseconds
|
||||||
|
{cache_update_interval, 5000},
|
||||||
{max_cache_size, #{
|
{max_cache_size, #{
|
||||||
elements => 1,
|
elements => 1,
|
||||||
memory => 2048 % 2Kb
|
% 2Kb
|
||||||
|
memory => 2048
|
||||||
}},
|
}},
|
||||||
{service_urls, #{
|
{service_urls, #{
|
||||||
'Repository' => <<"http://dominant:8022/v1/domain/repository">>,
|
'Repository' => <<"http://dominant:8022/v1/domain/repository">>,
|
||||||
'RepositoryClient' => <<"http://dominant:8022/v1/domain/repository_client">>
|
'RepositoryClient' => <<"http://dominant:8022/v1/domain/repository_client">>
|
||||||
}}
|
}}
|
||||||
]),
|
]),
|
||||||
[{apps, Apps}|C].
|
[{apps, Apps} | C].
|
||||||
|
|
||||||
-spec end_per_suite(config()) ->
|
|
||||||
any().
|
|
||||||
|
|
||||||
|
-spec end_per_suite(config()) -> any().
|
||||||
end_per_suite(C) ->
|
end_per_suite(C) ->
|
||||||
genlib_app:stop_unload_applications(?config(apps, C)).
|
genlib_app:stop_unload_applications(?config(apps, C)).
|
||||||
|
|
||||||
@ -91,63 +85,47 @@ end_per_suite(C) ->
|
|||||||
|
|
||||||
-spec commit(dmt_client:version(), dmt_client:commit(), dmt_client:transport_opts()) ->
|
-spec commit(dmt_client:version(), dmt_client:commit(), dmt_client:transport_opts()) ->
|
||||||
dmt_client:version() | no_return().
|
dmt_client:version() | no_return().
|
||||||
|
|
||||||
commit(Version, _Commit, _Opts) ->
|
commit(Version, _Commit, _Opts) ->
|
||||||
Version.
|
Version.
|
||||||
|
|
||||||
-spec checkout(dmt_client:ref(), dmt_client:transport_opts()) ->
|
-spec checkout(dmt_client:ref(), dmt_client:transport_opts()) -> dmt_client:snapshot() | no_return().
|
||||||
dmt_client:snapshot() | no_return().
|
|
||||||
|
|
||||||
checkout({version, ?notfound_version}, _Opts) ->
|
checkout({version, ?notfound_version}, _Opts) ->
|
||||||
erlang:throw(#'VersionNotFound'{});
|
erlang:throw(#'VersionNotFound'{});
|
||||||
|
|
||||||
checkout({version, ?unavailable_version}, _Opts) ->
|
checkout({version, ?unavailable_version}, _Opts) ->
|
||||||
woody_error:raise(system, {external, resource_unavailable, <<"test">>});
|
woody_error:raise(system, {external, resource_unavailable, <<"test">>});
|
||||||
|
|
||||||
checkout({version, ?existing_version}, _Opts) ->
|
checkout({version, ?existing_version}, _Opts) ->
|
||||||
timer:sleep(5000),
|
timer:sleep(5000),
|
||||||
#'Snapshot'{version = ?existing_version, domain = dmt_domain:new()};
|
#'Snapshot'{version = ?existing_version, domain = dmt_domain:new()};
|
||||||
|
|
||||||
checkout({head, #'Head'{}}, _Opts) ->
|
checkout({head, #'Head'{}}, _Opts) ->
|
||||||
timer:sleep(5000),
|
timer:sleep(5000),
|
||||||
#'Snapshot'{version = ?existing_version, domain = dmt_domain:new()}.
|
#'Snapshot'{version = ?existing_version, domain = dmt_domain:new()}.
|
||||||
|
|
||||||
-spec checkout_object(dmt_client:ref(), dmt_client:object_ref(), dmt_client:transport_opts()) ->
|
-spec checkout_object(dmt_client:ref(), dmt_client:object_ref(), dmt_client:transport_opts()) ->
|
||||||
dmsl_domain_thrift:'DomainObject'() | no_return().
|
dmsl_domain_thrift:'DomainObject'() | no_return().
|
||||||
|
|
||||||
checkout_object(_Reference, _ObjectReference, _Opts) ->
|
checkout_object(_Reference, _ObjectReference, _Opts) ->
|
||||||
erlang:throw(#'ObjectNotFound'{}).
|
erlang:throw(#'ObjectNotFound'{}).
|
||||||
|
|
||||||
-spec pull_range(dmt_client:version(), dmt_client:limit(), dmt_client:transport_opts()) ->
|
-spec pull_range(dmt_client:version(), dmt_client:limit(), dmt_client:transport_opts()) ->
|
||||||
dmt_client:history() | no_return().
|
dmt_client:history() | no_return().
|
||||||
|
|
||||||
pull_range(_Version, _Limit, _Opts) ->
|
pull_range(_Version, _Limit, _Opts) ->
|
||||||
timer:sleep(5000),
|
timer:sleep(5000),
|
||||||
#{}.
|
#{}.
|
||||||
|
|
||||||
%%% Tests
|
%%% Tests
|
||||||
|
|
||||||
-spec get_snapshot_success(config()) ->
|
-spec get_snapshot_success(config()) -> any().
|
||||||
any().
|
|
||||||
|
|
||||||
get_snapshot_success(_C) ->
|
get_snapshot_success(_C) ->
|
||||||
{ok, #'Snapshot'{}} = dmt_client_cache:get(?existing_version).
|
{ok, #'Snapshot'{}} = dmt_client_cache:get(?existing_version).
|
||||||
|
|
||||||
-spec snapshot_not_found(config()) ->
|
-spec snapshot_not_found(config()) -> any().
|
||||||
any().
|
|
||||||
|
|
||||||
snapshot_not_found(_C) ->
|
snapshot_not_found(_C) ->
|
||||||
{error, version_not_found} = dmt_client_cache:get(1).
|
{error, version_not_found} = dmt_client_cache:get(1).
|
||||||
|
|
||||||
-spec woody_error(config()) ->
|
-spec woody_error(config()) -> any().
|
||||||
any().
|
|
||||||
|
|
||||||
woody_error(_C) ->
|
woody_error(_C) ->
|
||||||
{error, {woody_error, _}} = dmt_client_cache:get(?unavailable_version).
|
{error, {woody_error, _}} = dmt_client_cache:get(?unavailable_version).
|
||||||
|
|
||||||
-spec object_not_found(config()) ->
|
-spec object_not_found(config()) -> any().
|
||||||
any().
|
|
||||||
|
|
||||||
object_not_found(_C) ->
|
object_not_found(_C) ->
|
||||||
Ref = {category, #'domain_CategoryRef'{id = 1}},
|
Ref = {category, #'domain_CategoryRef'{id = 1}},
|
||||||
{error, version_not_found} = dmt_client_cache:get_object(?notfound_version, Ref),
|
{error, version_not_found} = dmt_client_cache:get_object(?notfound_version, Ref),
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
-module(dmt_client_tests_SUITE).
|
-module(dmt_client_tests_SUITE).
|
||||||
|
|
||||||
-include_lib("common_test/include/ct.hrl").
|
-include_lib("common_test/include/ct.hrl").
|
||||||
|
|
||||||
-export([all/0]).
|
-export([all/0]).
|
||||||
@ -31,17 +32,19 @@ groups() ->
|
|||||||
-spec init_per_suite(term()) -> term().
|
-spec init_per_suite(term()) -> term().
|
||||||
init_per_suite(C) ->
|
init_per_suite(C) ->
|
||||||
Apps = genlib_app:start_application_with(dmt_client, [
|
Apps = genlib_app:start_application_with(dmt_client, [
|
||||||
{cache_update_interval, 5000}, % milliseconds
|
% milliseconds
|
||||||
|
{cache_update_interval, 5000},
|
||||||
{max_cache_size, #{
|
{max_cache_size, #{
|
||||||
elements => 1,
|
elements => 1,
|
||||||
memory => 2048 % 2Kb
|
% 2Kb
|
||||||
|
memory => 2048
|
||||||
}},
|
}},
|
||||||
{service_urls, #{
|
{service_urls, #{
|
||||||
'Repository' => <<"http://dominant:8022/v1/domain/repository">>,
|
'Repository' => <<"http://dominant:8022/v1/domain/repository">>,
|
||||||
'RepositoryClient' => <<"http://dominant:8022/v1/domain/repository_client">>
|
'RepositoryClient' => <<"http://dominant:8022/v1/domain/repository_client">>
|
||||||
}}
|
}}
|
||||||
]),
|
]),
|
||||||
[{apps, Apps}|C].
|
[{apps, Apps} | C].
|
||||||
|
|
||||||
-spec end_per_suite(term()) -> term().
|
-spec end_per_suite(term()) -> term().
|
||||||
end_per_suite(C) ->
|
end_per_suite(C) ->
|
||||||
|
Loading…
Reference in New Issue
Block a user