diff options
Diffstat (limited to 'src/couch_eval/src/couch_eval.erl')
-rw-r--r-- | src/couch_eval/src/couch_eval.erl | 55 |
1 files changed, 53 insertions, 2 deletions
diff --git a/src/couch_eval/src/couch_eval.erl b/src/couch_eval/src/couch_eval.erl index 3541a5b94..f87ba97b9 100644 --- a/src/couch_eval/src/couch_eval.erl +++ b/src/couch_eval/src/couch_eval.erl @@ -17,7 +17,9 @@ -export([ acquire_map_context/6, release_map_context/1, - map_docs/2 + map_docs/2, + with_context/2, + try_compile/4 ]). @@ -35,6 +37,10 @@ -type result() :: {doc_id(), [[{any(), any()}]]}. -type api_mod() :: atom(). -type context() :: {api_mod(), any()}. +-type function_type() :: binary() | atom(). +-type function_name() :: binary(). +-type function_src() :: binary(). +-type error(_Error) :: no_return(). -type context_opts() :: #{ db_name := db_name(), @@ -46,10 +52,17 @@ api_mod => api_mod() }. +-type with_context_opts() :: #{ + language := language() +}. + -callback acquire_map_context(context_opts()) -> {ok, any()} | {error, any()}. -callback release_map_context(context()) -> ok | {error, any()}. -callback map_docs(context(), [doc()]) -> {ok, [result()]} | {error, any()}. +-callback acquire_context() -> {ok, any()} | {error, any()}. +-callback release_context(context()) -> ok | {error, any()}. +-callback try_compile(context(), function_type(), function_name(), function_src()) -> ok. -spec acquire_map_context( @@ -59,7 +72,10 @@ sig(), lib(), map_funs() - ) -> {ok, context()} | {error, any()}. + ) -> + {ok, context()} + | error({invalid_eval_api_mod, Language :: binary()}) + | error({unknown_eval_api_language, Language :: binary()}). acquire_map_context(DbName, DDocId, Language, Sig, Lib, MapFuns) -> ApiMod = get_api_mod(Language), CtxOpts = #{ @@ -87,6 +103,41 @@ map_docs({ApiMod, Ctx}, Docs) -> ApiMod:map_docs(Ctx, Docs). +-spec with_context(with_context_opts(), function()) -> + any() + | error({invalid_eval_api_mod, Language :: binary()}) + | error({unknown_eval_api_language, Language :: binary()}). +with_context(#{language := Language}, Fun) -> + {ok, Ctx} = acquire_context(Language), + try + Fun(Ctx) + after + release_context(Ctx) + end. + + +-spec try_compile(context(), function_type(), function_name(), function_src()) -> ok. +try_compile({_ApiMod, _Ctx}, reduce, <<_/binary>>, disabled) -> + % Reduce functions may be disabled. Accept that as a valid configuration. + ok; + +try_compile({ApiMod, Ctx}, FuncType, FuncName, FuncSrc) -> + ApiMod:try_compile(Ctx, FuncType, FuncName, FuncSrc). + + +acquire_context(Language) -> + ApiMod = get_api_mod(Language), + {ok, Ctx} = ApiMod:acquire_context(), + {ok, {ApiMod, Ctx}}. + + +release_context(nil) -> + ok; + +release_context({ApiMod, Ctx}) -> + ApiMod:release_context(Ctx). + + get_api_mod(Language) when is_binary(Language) -> try LangStr = binary_to_list(Language), |