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:
|
||||
- make rebar3
|
||||
script:
|
||||
- make && make test
|
||||
script: make && make test
|
||||
language: erlang
|
||||
otp_release:
|
||||
- 18.2.1
|
||||
- 17.5
|
||||
- 19.2
|
||||
- 18.3
|
||||
|
||||
|
34
Makefile
34
Makefile
@ -4,7 +4,7 @@
|
||||
## @description
|
||||
## 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 ?=
|
||||
VMI ?= fogfish/erlang
|
||||
NET ?= lo0
|
||||
URL ?= undefined
|
||||
URL ?= undefined
|
||||
LATEST ?= latest
|
||||
|
||||
## rebar version (no spaces at end)
|
||||
REBAR ?= 3.3.2
|
||||
|
||||
## root path to benchmark framework
|
||||
BB = ../basho_bench
|
||||
SSHENV = /tmp/ssh-agent.conf
|
||||
@ -46,17 +49,17 @@ EFLAGS = \
|
||||
## 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_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 = \
|
||||
-module(test). \
|
||||
-export([run/1]). \
|
||||
run(Spec) -> \
|
||||
{ok, Test} = file:consult(Spec), \
|
||||
case lists:keyfind(node, 1, Test) of \
|
||||
false -> ct:run_test([{spec, Spec}]); \
|
||||
-module(test). \
|
||||
-export([run/1]). \
|
||||
run(Spec) -> \
|
||||
{ok, Test} = file:consult(Spec), \
|
||||
Error = case lists:keyfind(node, 1, Test) of \
|
||||
false -> element(2, ct:run_test([{spec, Spec}])); \
|
||||
true -> ct_master:run(Spec) \
|
||||
end, \
|
||||
erlang:halt().
|
||||
end, \
|
||||
erlang:halt(Error).
|
||||
|
||||
#####################################################################
|
||||
##
|
||||
@ -119,7 +122,7 @@ relx.config: rel/relx.config.src
|
||||
@cat $< | sed 's/release/release, {${APP}, "${VSN}"}/' > $@
|
||||
else
|
||||
${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` ;\
|
||||
docker cp $$I:/${APP}/$@ $@ ;\
|
||||
docker rm -f $$I ;\
|
||||
@ -136,7 +139,7 @@ docker: rel/Dockerfile
|
||||
--build-arg APP=${APP} \
|
||||
--build-arg VSN=${VSN} \
|
||||
-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:
|
||||
@curl -L -O https://s3.amazonaws.com/rebar3/rebar3 ; \
|
||||
chmod ugo+x $@
|
||||
@echo "==> install rebar (${REBAR})" ;\
|
||||
curl -L -O --progress-bar https://github.com/erlang/rebar3/releases/download/${REBAR}/rebar3 ;\
|
||||
chmod +x $@
|
||||
|
||||
.PHONY: test rel deps all pkg
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
{application, cache,
|
||||
[
|
||||
{description, "in-memory cache"},
|
||||
{vsn, "2.1.1"},
|
||||
{vsn, "2.2.0"},
|
||||
{modules, []},
|
||||
{registered, []},
|
||||
{applications,[
|
||||
|
@ -62,7 +62,11 @@
|
||||
remove/2,
|
||||
remove/3,
|
||||
remove_/2,
|
||||
remove_/3
|
||||
remove_/3,
|
||||
apply/3,
|
||||
apply/4,
|
||||
apply_/4,
|
||||
apply_/3
|
||||
]).
|
||||
%% extended cache i/o interface
|
||||
-export([
|
||||
@ -303,6 +307,36 @@ remove_(Cache, Key, true) ->
|
||||
remove_(Cache, Key, false) ->
|
||||
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
|
||||
|
@ -121,6 +121,10 @@ handle_call({ttl, Key}, _, State) ->
|
||||
handle_call({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) ->
|
||||
{Result, State1} = cache_acc(Key, Val, State0),
|
||||
{reply, Result, State1};
|
||||
@ -328,6 +332,16 @@ cache_remove(Key, #cache{name=_Name, heap=Heap}=State) ->
|
||||
?DEBUG("cache ~p: remove ~p~n", [_Name, Key]),
|
||||
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
|
||||
cache_acc(Key, Val, State)
|
||||
|
@ -42,7 +42,9 @@
|
||||
lookup/1,
|
||||
has/1,
|
||||
remove/1,
|
||||
remove_/1
|
||||
remove_/1,
|
||||
apply/1,
|
||||
apply_/1
|
||||
]).
|
||||
|
||||
%%
|
||||
@ -77,7 +79,7 @@ groups() ->
|
||||
{primitives, [parallel],
|
||||
[lifecycle]},
|
||||
{basic_io, [parallel],
|
||||
[put, put_, get, lookup, has, remove, remove_]},
|
||||
[put, put_, get, lookup, has, remove, remove_, apply, apply_]},
|
||||
{extended_io, [parallel],
|
||||
[acc, set, add, replace, append, append_, prepend, prepend_, delete]}
|
||||
].
|
||||
@ -169,6 +171,22 @@ remove_(_Config) ->
|
||||
false= cache:has(Cache, key),
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user