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
----------------------------------------------------------------------