You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by kx...@apache.org on 2015/10/27 20:35:32 UTC
[1/2] couchdb-couch-epi git commit: Add couch_epi:decide/5
Repository: couchdb-couch-epi
Updated Branches:
refs/heads/master 77dfaf413 -> 807aa3f58
Add couch_epi:decide/5
There are cases when we want to call configured providers until any of
them would make a decision. We also would want to be able to find out
if any decision has been made so we could call default handler.
Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-epi/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-epi/commit/86531ee4
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-epi/tree/86531ee4
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-epi/diff/86531ee4
Branch: refs/heads/master
Commit: 86531ee40193051f1d7572f72eb6b852563cd179
Parents: be34447
Author: ILYA Khlopotov <ii...@ca.ibm.com>
Authored: Fri Oct 9 12:55:41 2015 -0700
Committer: ILYA Khlopotov <ii...@ca.ibm.com>
Committed: Fri Oct 9 15:53:54 2015 -0700
----------------------------------------------------------------------
README.md | 16 ++++++++
src/couch_epi.erl | 9 ++++-
src/couch_epi_functions_gen.erl | 77 +++++++++++++++++++++++++++++++++++-
3 files changed, 99 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-couch-epi/blob/86531ee4/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 3f15a62..88390d0 100644
--- a/README.md
+++ b/README.md
@@ -97,6 +97,22 @@ Notes:
- `concurrent` is incompatible with `pipe`
+## decide functionality
+
+There are cases when we want to call configured providers until any of them
+would make a decission. We also would want to be able to find out if any
+decision has been made so we could call default handler. In order to be able
+to do so there is couch_epi:decide/5. Every service which uses this feature
+would get either:
+
+ - no_decision
+ - {decided, Decision :: term()}
+
+The provider module should return one of the above results. The current logic is
+to call all configured providers in order of their definition until we get
+`{decided, term()}`. If none of the providers would return this term we would
+return `no_decision`.
+
# couch_epi_plugin behaviour
The module implementing behaviour need to export following functions:
http://git-wip-us.apache.org/repos/asf/couchdb-couch-epi/blob/86531ee4/src/couch_epi.erl
----------------------------------------------------------------------
diff --git a/src/couch_epi.erl b/src/couch_epi.erl
index 2754261..0ccef90 100644
--- a/src/couch_epi.erl
+++ b/src/couch_epi.erl
@@ -22,7 +22,7 @@
keys/1, subscribers/1]).
%% apply
--export([apply/5]).
+-export([apply/5, decide/5]).
-export([any/5, all/5]).
-export([is_configured/3]).
@@ -168,3 +168,10 @@ is_configured(Handle, Function, Arity) when Handle /= undefined ->
register_service(Plugin, Children) ->
couch_epi_sup:plugin_childspecs(Plugin, Children).
+
+-spec decide(Handle :: handle(), ServiceId :: atom(), Function :: atom(),
+ Args :: [term()], Opts :: apply_opts()) ->
+ no_decision | {decided, term()}.
+
+decide(Handle, ServiceId, Function, Args, Opts) when Handle /= undefined ->
+ couch_epi_functions_gen:decide(Handle, ServiceId, Function, Args, Opts).
http://git-wip-us.apache.org/repos/asf/couchdb-couch-epi/blob/86531ee4/src/couch_epi_functions_gen.erl
----------------------------------------------------------------------
diff --git a/src/couch_epi_functions_gen.erl b/src/couch_epi_functions_gen.erl
index 4990b60..df1d916 100644
--- a/src/couch_epi_functions_gen.erl
+++ b/src/couch_epi_functions_gen.erl
@@ -22,7 +22,8 @@
-export([
apply/4,
apply/5,
- modules/3
+ modules/3,
+ decide/5
]).
-ifdef(TEST).
@@ -34,7 +35,8 @@
-record(opts, {
ignore_errors = false,
pipe = false,
- concurrent = false
+ concurrent = false,
+ interruptible = false
}).
get_handle(ServiceId) ->
@@ -51,6 +53,15 @@ apply(Handle, _ServiceId, Function, Args, Opts) ->
Modules = providers(Handle, Function, length(Args), DispatchOpts),
dispatch(Handle, Modules, Function, Args, DispatchOpts).
+-spec decide(Handle :: atom(), ServiceId :: atom(), Function :: atom(),
+ Args :: [term()], Opts :: couch_epi:apply_opts()) ->
+ no_decision | {decided, term()}.
+
+decide(Handle, _ServiceId, Function, Args, Opts) ->
+ DispatchOpts = parse_opts([interruptible|Opts]),
+ Modules = providers(Handle, Function, length(Args), DispatchOpts),
+ dispatch(Handle, Modules, Function, Args, DispatchOpts).
+
%% ------------------------------------------------------------------
%% Codegeneration routines
%% ------------------------------------------------------------------
@@ -241,6 +252,9 @@ dispatch(Handle, Modules, Function, Args,
lists:foldl(fun(Module, Acc) ->
Handle:dispatch(Module, Function, Acc)
end, Args, Modules);
+dispatch(Handle, Modules, Function, Args,
+ #opts{interruptible = true}) ->
+ apply_while(Modules, Handle, Function, Args);
dispatch(Handle, Modules, Function, Args, #opts{} = Opts) ->
[do_dispatch(Handle, Module, Function, Args, Opts) || Module <- Modules].
@@ -258,6 +272,15 @@ do_dispatch(Handle, Module, Function, Args,
do_dispatch(Handle, Module, Function, Args, #opts{}) ->
Handle:dispatch(Module, Function, Args).
+apply_while([], _Handle, _Function, _Args) ->
+ no_decision;
+apply_while([Module | Modules], Handle, Function, Args) ->
+ case Handle:dispatch(Module, Function, Args) of
+ no_decision ->
+ apply_while(Modules, Handle, Function, Args);
+ {decided, _Decission} = Result ->
+ Result
+ end.
parse_opts(Opts) ->
parse_opts(Opts, #opts{}).
@@ -268,6 +291,8 @@ parse_opts([pipe|Rest], #opts{} = Acc) ->
parse_opts(Rest, Acc#opts{pipe = true});
parse_opts([concurrent|Rest], #opts{} = Acc) ->
parse_opts(Rest, Acc#opts{concurrent = true});
+parse_opts([interruptible|Rest], #opts{} = Acc) ->
+ parse_opts(Rest, Acc#opts{interruptible = true});
parse_opts([], Acc) ->
Acc.
@@ -326,4 +351,52 @@ basic_test() ->
ok.
+generate_module(Name, Body) ->
+ Tokens = couch_epi_codegen:scan(Body),
+ couch_epi_codegen:generate(Name, Tokens).
+
+decide_module(decide) ->
+ "
+ -export([inc/1]).
+
+ inc(A) ->
+ {decided, A + 1}.
+ ";
+decide_module(no_decision) ->
+ "
+ -export([inc/1]).
+
+ inc(_A) ->
+ no_decision.
+ ".
+
+decide_test() ->
+ ok = generate_module(decide, decide_module(decide)),
+ ok = generate_module(no_decision, decide_module(no_decision)),
+
+ DecideDef = {foo_app, [{decide, [{inc, 1}]}]},
+ NoDecissionDef = {bar_app, [{no_decision, [{inc, 1}]}]},
+
+ DecideFirstHandle = decide_first_handle,
+ ok = generate(DecideFirstHandle, [DecideDef, NoDecissionDef]),
+ ?assertMatch([decide, no_decision], DecideFirstHandle:providers(inc, 1)),
+ ?assertMatch({decided,4}, decide(DecideFirstHandle, anything, inc, [3], [])),
+
+ DecideSecondHandle = decide_second_handle,
+ ok = generate(DecideSecondHandle, [NoDecissionDef, DecideDef]),
+ ?assertMatch([no_decision, decide], DecideSecondHandle:providers(inc, 1)),
+ ?assertMatch({decided,4}, decide(DecideSecondHandle, anything, inc, [3], [])),
+
+ NoDecissionHandle = no_decision_handle,
+ ok = generate(NoDecissionHandle, [NoDecissionDef]),
+ ?assertMatch([no_decision], NoDecissionHandle:providers(inc, 1)),
+ ?assertMatch(no_decision, decide(NoDecissionHandle, anything, inc, [3], [])),
+
+ NoHandle = no_handle,
+ ok = generate(NoHandle, []),
+ ?assertMatch([], NoHandle:providers(inc, 1)),
+ ?assertMatch(no_decision, decide(NoHandle, anything, inc, [3], [])),
+
+ ok.
+
-endif.
[2/2] couchdb-couch-epi git commit: Merge remote-tracking branch
'github/pr/15'
Posted by kx...@apache.org.
Merge remote-tracking branch 'github/pr/15'
Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-epi/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-epi/commit/807aa3f5
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-epi/tree/807aa3f5
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-epi/diff/807aa3f5
Branch: refs/heads/master
Commit: 807aa3f58e39f1273e732020c80d630d9177790c
Parents: 77dfaf4 86531ee
Author: Alexander Shorin <kx...@apache.org>
Authored: Tue Oct 27 22:31:11 2015 +0300
Committer: Alexander Shorin <kx...@apache.org>
Committed: Tue Oct 27 22:31:11 2015 +0300
----------------------------------------------------------------------
README.md | 16 ++++++++
src/couch_epi.erl | 9 ++++-
src/couch_epi_functions_gen.erl | 77 +++++++++++++++++++++++++++++++++++-
3 files changed, 99 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-couch-epi/blob/807aa3f5/README.md
----------------------------------------------------------------------
diff --cc README.md
index 7d5cc70,88390d0..5b5223f
--- a/README.md
+++ b/README.md
@@@ -96,11 -96,23 +96,27 @@@ There are multiple ways of doing the ap
Notes:
- `concurrent` is incompatible with `pipe`
+ - if there are multiple plugins providing same service they will be called in the order
+ they listed in application:get_env(couch_epi, plugins)
+ - if the same plugin provides multiple implementations of the same service
+ the order is as defined in providers callback
+ ## decide functionality
+
+ There are cases when we want to call configured providers until any of them
+ would make a decission. We also would want to be able to find out if any
+ decision has been made so we could call default handler. In order to be able
+ to do so there is couch_epi:decide/5. Every service which uses this feature
+ would get either:
+
+ - no_decision
+ - {decided, Decision :: term()}
+
+ The provider module should return one of the above results. The current logic is
+ to call all configured providers in order of their definition until we get
+ `{decided, term()}`. If none of the providers would return this term we would
+ return `no_decision`.
+
# couch_epi_plugin behaviour
The module implementing behaviour need to export following functions:
http://git-wip-us.apache.org/repos/asf/couchdb-couch-epi/blob/807aa3f5/src/couch_epi.erl
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-couch-epi/blob/807aa3f5/src/couch_epi_functions_gen.erl
----------------------------------------------------------------------