mirror of
https://github.com/valitydev/cache.git
synced 2024-11-06 01:45:19 +00:00
(#15) : add atomic apply function to modify value
This commit is contained in:
parent
9f31083a2a
commit
4ca5b8caba
@ -1,9 +1,6 @@
|
|||||||
install:
|
script: make && make test
|
||||||
- make rebar3
|
|
||||||
script:
|
|
||||||
- make && make test
|
|
||||||
language: erlang
|
language: erlang
|
||||||
otp_release:
|
otp_release:
|
||||||
- 18.2.1
|
- 19.2
|
||||||
- 17.5
|
- 18.3
|
||||||
|
|
||||||
|
34
Makefile
34
Makefile
@ -4,7 +4,7 @@
|
|||||||
## @description
|
## @description
|
||||||
## Makefile to build and release Erlang applications using standard development tools
|
## Makefile to build and release Erlang applications using standard development tools
|
||||||
##
|
##
|
||||||
## @version 0.11.5
|
## @version 0.11.8
|
||||||
|
|
||||||
#####################################################################
|
#####################################################################
|
||||||
##
|
##
|
||||||
@ -22,9 +22,12 @@ TEST ?= ${APP}
|
|||||||
S3 ?=
|
S3 ?=
|
||||||
VMI ?= fogfish/erlang
|
VMI ?= fogfish/erlang
|
||||||
NET ?= lo0
|
NET ?= lo0
|
||||||
URL ?= undefined
|
URL ?= undefined
|
||||||
LATEST ?= latest
|
LATEST ?= latest
|
||||||
|
|
||||||
|
## rebar version (no spaces at end)
|
||||||
|
REBAR ?= 3.3.2
|
||||||
|
|
||||||
## root path to benchmark framework
|
## root path to benchmark framework
|
||||||
BB = ../basho_bench
|
BB = ../basho_bench
|
||||||
SSHENV = /tmp/ssh-agent.conf
|
SSHENV = /tmp/ssh-agent.conf
|
||||||
@ -46,17 +49,17 @@ EFLAGS = \
|
|||||||
## self-extracting bundle wrapper
|
## self-extracting bundle wrapper
|
||||||
BUNDLE_INIT = PREFIX=${PREFIX}\nREL=${PREFIX}/${REL}\nAPP=${APP}\nVSN=${VSN}\nLINE=`grep -a -n "BUNDLE:$$" $$0`\nmkdir -p $${REL}\ntail -n +$$(( $${LINE%%%%:*} + 1)) $$0 | gzip -vdc - | tar -C $${REL} -xvf - > /dev/null\n
|
BUNDLE_INIT = PREFIX=${PREFIX}\nREL=${PREFIX}/${REL}\nAPP=${APP}\nVSN=${VSN}\nLINE=`grep -a -n "BUNDLE:$$" $$0`\nmkdir -p $${REL}\ntail -n +$$(( $${LINE%%%%:*} + 1)) $$0 | gzip -vdc - | tar -C $${REL} -xvf - > /dev/null\n
|
||||||
BUNDLE_FREE = exit\nBUNDLE:\n
|
BUNDLE_FREE = exit\nBUNDLE:\n
|
||||||
BUILDER = FROM ${VMI}\nRUN mkdir ${APP}\nCOPY . ${APP}/\nRUN cd ${APP} && make && make rel\n
|
BUILDER = FROM ${VMI}\nARG VERSION=\nRUN mkdir ${APP}\nCOPY . ${APP}/\nRUN cd ${APP} && make VSN=\x24{VERSION} && make rel VSN=\x24{VERSION}\n
|
||||||
CTRUN = \
|
CTRUN = \
|
||||||
-module(test). \
|
-module(test). \
|
||||||
-export([run/1]). \
|
-export([run/1]). \
|
||||||
run(Spec) -> \
|
run(Spec) -> \
|
||||||
{ok, Test} = file:consult(Spec), \
|
{ok, Test} = file:consult(Spec), \
|
||||||
case lists:keyfind(node, 1, Test) of \
|
Error = case lists:keyfind(node, 1, Test) of \
|
||||||
false -> ct:run_test([{spec, Spec}]); \
|
false -> element(2, ct:run_test([{spec, Spec}])); \
|
||||||
true -> ct_master:run(Spec) \
|
true -> ct_master:run(Spec) \
|
||||||
end, \
|
end, \
|
||||||
erlang:halt().
|
erlang:halt(Error).
|
||||||
|
|
||||||
#####################################################################
|
#####################################################################
|
||||||
##
|
##
|
||||||
@ -119,7 +122,7 @@ relx.config: rel/relx.config.src
|
|||||||
@cat $< | sed 's/release/release, {${APP}, "${VSN}"}/' > $@
|
@cat $< | sed 's/release/release, {${APP}, "${VSN}"}/' > $@
|
||||||
else
|
else
|
||||||
${PKG}.tar.gz: _build/dockermake
|
${PKG}.tar.gz: _build/dockermake
|
||||||
@docker build --file=$< --force-rm=true --tag=build/${APP}:latest . ;\
|
@docker build --file=$< --force-rm=true --build-arg="VERSION=${VSN}" --tag=build/${APP}:latest . ;\
|
||||||
I=`docker create build/${APP}:latest` ;\
|
I=`docker create build/${APP}:latest` ;\
|
||||||
docker cp $$I:/${APP}/$@ $@ ;\
|
docker cp $$I:/${APP}/$@ $@ ;\
|
||||||
docker rm -f $$I ;\
|
docker rm -f $$I ;\
|
||||||
@ -136,7 +139,7 @@ docker: rel/Dockerfile
|
|||||||
--build-arg APP=${APP} \
|
--build-arg APP=${APP} \
|
||||||
--build-arg VSN=${VSN} \
|
--build-arg VSN=${VSN} \
|
||||||
-t ${URL}/${APP}:${VSN} -f $< .
|
-t ${URL}/${APP}:${VSN} -f $< .
|
||||||
docker tag -f ${URL}/${APP}:${VSN} ${URL}/${APP}:${LATEST}
|
docker tag ${URL}/${APP}:${VSN} ${URL}/${APP}:${LATEST}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -207,8 +210,9 @@ console: ${PKG}.tar.gz
|
|||||||
##
|
##
|
||||||
#####################################################################
|
#####################################################################
|
||||||
rebar3:
|
rebar3:
|
||||||
@curl -L -O https://s3.amazonaws.com/rebar3/rebar3 ; \
|
@echo "==> install rebar (${REBAR})" ;\
|
||||||
chmod ugo+x $@
|
curl -L -O --progress-bar https://github.com/erlang/rebar3/releases/download/${REBAR}/rebar3 ;\
|
||||||
|
chmod +x $@
|
||||||
|
|
||||||
.PHONY: test rel deps all pkg
|
.PHONY: test rel deps all pkg
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{application, cache,
|
{application, cache,
|
||||||
[
|
[
|
||||||
{description, "in-memory cache"},
|
{description, "in-memory cache"},
|
||||||
{vsn, "2.1.1"},
|
{vsn, "2.2.0"},
|
||||||
{modules, []},
|
{modules, []},
|
||||||
{registered, []},
|
{registered, []},
|
||||||
{applications,[
|
{applications,[
|
||||||
|
@ -62,7 +62,11 @@
|
|||||||
remove/2,
|
remove/2,
|
||||||
remove/3,
|
remove/3,
|
||||||
remove_/2,
|
remove_/2,
|
||||||
remove_/3
|
remove_/3,
|
||||||
|
apply/3,
|
||||||
|
apply/4,
|
||||||
|
apply_/4,
|
||||||
|
apply_/3
|
||||||
]).
|
]).
|
||||||
%% extended cache i/o interface
|
%% extended cache i/o interface
|
||||||
-export([
|
-export([
|
||||||
@ -303,6 +307,36 @@ remove_(Cache, Key, true) ->
|
|||||||
remove_(Cache, Key, false) ->
|
remove_(Cache, Key, false) ->
|
||||||
send(Cache, {remove, Key}).
|
send(Cache, {remove, Key}).
|
||||||
|
|
||||||
|
%%
|
||||||
|
%% synchronous apply function to entity on cache
|
||||||
|
%% the function maps element, the new value is returned
|
||||||
|
%% the operation prolongs value ttl
|
||||||
|
-spec apply(cache(), key(), fun((_) -> _)) -> val() | undefined.
|
||||||
|
-spec apply(cache(), key(), fun((_) -> _), timeout()) -> val() | undefined.
|
||||||
|
|
||||||
|
apply(Cache, Key, Fun) ->
|
||||||
|
cache:apply(Cache, Key, Fun, ?CONFIG_TIMEOUT).
|
||||||
|
|
||||||
|
apply(Cache, Key, Fun, Timeout) ->
|
||||||
|
call(Cache, {apply, Key, Fun}, Timeout).
|
||||||
|
|
||||||
|
|
||||||
|
%%
|
||||||
|
%% asynchronous apply function to entity on cache
|
||||||
|
%% the function maps element, the new value is returned
|
||||||
|
%% the operation prolongs value ttl
|
||||||
|
-spec apply_(cache(), key(), fun((_) -> _)) -> ok | reference().
|
||||||
|
-spec apply_(cache(), key(), fun((_) -> _), true | false) -> ok | reference().
|
||||||
|
|
||||||
|
apply_(Cache, Key, Fun) ->
|
||||||
|
cache:apply_(Cache, Key, Fun, false).
|
||||||
|
|
||||||
|
apply_(Cache, Key, Fun, true) ->
|
||||||
|
cast(Cache, {apply, Key, Fun});
|
||||||
|
|
||||||
|
apply_(Cache, Key, Fun, false) ->
|
||||||
|
cast(Cache, {apply, Key, Fun}).
|
||||||
|
|
||||||
%%%----------------------------------------------------------------------------
|
%%%----------------------------------------------------------------------------
|
||||||
%%%
|
%%%
|
||||||
%%% extended cache i/o interface
|
%%% extended cache i/o interface
|
||||||
|
@ -121,6 +121,10 @@ handle_call({ttl, Key}, _, State) ->
|
|||||||
handle_call({remove, Key}, _, State) ->
|
handle_call({remove, Key}, _, State) ->
|
||||||
{reply, ok, cache_remove(Key, State)};
|
{reply, ok, cache_remove(Key, State)};
|
||||||
|
|
||||||
|
handle_call({apply, Key, Fun}, _, State0) ->
|
||||||
|
{Result, State1} = cache_apply(Key, Fun, State0),
|
||||||
|
{reply, Result, State1};
|
||||||
|
|
||||||
handle_call({acc, Key, Val}, _, State0) ->
|
handle_call({acc, Key, Val}, _, State0) ->
|
||||||
{Result, State1} = cache_acc(Key, Val, State0),
|
{Result, State1} = cache_acc(Key, Val, State0),
|
||||||
{reply, Result, State1};
|
{reply, Result, State1};
|
||||||
@ -328,6 +332,16 @@ cache_remove(Key, #cache{name=_Name, heap=Heap}=State) ->
|
|||||||
?DEBUG("cache ~p: remove ~p~n", [_Name, Key]),
|
?DEBUG("cache ~p: remove ~p~n", [_Name, Key]),
|
||||||
State.
|
State.
|
||||||
|
|
||||||
|
%%
|
||||||
|
%%
|
||||||
|
cache_apply(Key, Fun, State) ->
|
||||||
|
case Fun(cache_get(Key, State)) of
|
||||||
|
undefined ->
|
||||||
|
{undefined, State};
|
||||||
|
Val ->
|
||||||
|
{Val, cache_put(Key, Val, undefined, State)}
|
||||||
|
end.
|
||||||
|
|
||||||
%%
|
%%
|
||||||
%% @todo: reduce one write
|
%% @todo: reduce one write
|
||||||
cache_acc(Key, Val, State)
|
cache_acc(Key, Val, State)
|
||||||
|
@ -42,7 +42,9 @@
|
|||||||
lookup/1,
|
lookup/1,
|
||||||
has/1,
|
has/1,
|
||||||
remove/1,
|
remove/1,
|
||||||
remove_/1
|
remove_/1,
|
||||||
|
apply/1,
|
||||||
|
apply_/1
|
||||||
]).
|
]).
|
||||||
|
|
||||||
%%
|
%%
|
||||||
@ -77,7 +79,7 @@ groups() ->
|
|||||||
{primitives, [parallel],
|
{primitives, [parallel],
|
||||||
[lifecycle]},
|
[lifecycle]},
|
||||||
{basic_io, [parallel],
|
{basic_io, [parallel],
|
||||||
[put, put_, get, lookup, has, remove, remove_]},
|
[put, put_, get, lookup, has, remove, remove_, apply, apply_]},
|
||||||
{extended_io, [parallel],
|
{extended_io, [parallel],
|
||||||
[acc, set, add, replace, append, append_, prepend, prepend_, delete]}
|
[acc, set, add, replace, append, append_, prepend, prepend_, delete]}
|
||||||
].
|
].
|
||||||
@ -169,6 +171,22 @@ remove_(_Config) ->
|
|||||||
false= cache:has(Cache, key),
|
false= cache:has(Cache, key),
|
||||||
ok = cache:drop(Cache).
|
ok = cache:drop(Cache).
|
||||||
|
|
||||||
|
apply(_Config) ->
|
||||||
|
{ok, Cache} = cache:start_link([]),
|
||||||
|
val = cache:apply(Cache, key, fun(undefined) -> val end),
|
||||||
|
val = cache:get(Cache, key),
|
||||||
|
lav = cache:apply(Cache, key, fun(val) -> lav end),
|
||||||
|
lav = cache:get(Cache, key),
|
||||||
|
ok = cache:drop(Cache).
|
||||||
|
|
||||||
|
apply_(_Config) ->
|
||||||
|
{ok, Cache} = cache:start_link([]),
|
||||||
|
cache:apply_(Cache, key, fun(undefined) -> val end),
|
||||||
|
val = cache:get(Cache, key),
|
||||||
|
cache:apply_(Cache, key, fun(val) -> lav end),
|
||||||
|
lav = cache:get(Cache, key),
|
||||||
|
ok = cache:drop(Cache).
|
||||||
|
|
||||||
%%%----------------------------------------------------------------------------
|
%%%----------------------------------------------------------------------------
|
||||||
%%%
|
%%%
|
||||||
%%% cache extended i/o
|
%%% cache extended i/o
|
||||||
|
Loading…
Reference in New Issue
Block a user