aboutsummaryrefslogtreecommitdiff
path: root/apps/dreki/src/dreki_tasks.erl
diff options
context:
space:
mode:
Diffstat (limited to 'apps/dreki/src/dreki_tasks.erl')
-rw-r--r--apps/dreki/src/dreki_tasks.erl141
1 files changed, 141 insertions, 0 deletions
diff --git a/apps/dreki/src/dreki_tasks.erl b/apps/dreki/src/dreki_tasks.erl
new file mode 100644
index 0000000..0899386
--- /dev/null
+++ b/apps/dreki/src/dreki_tasks.erl
@@ -0,0 +1,141 @@
+-module(dreki_tasks).
+-include("dreki.hrl").
+
+-behaviour(dreki_store_namespace).
+-export([start/0, version/0, valid_store/4, format_item/1, schemas/0, new/0]).
+
+%% old stuff
+-export([resolve/1, exists/1, read_uri/2]).
+
+start() -> ok.
+
+valid_store(_Namespace, _Location, _Name, _BackendMod) -> ok.
+
+format_item(Item) -> ok.
+
+handlers() -> [dreki_tasks_script, dreki_tasks_cloyster].
+
+-record(?MODULE, {
+ id,
+ version,
+ schema,
+ handler,
+ handler_manifest
+}).
+
+version() -> 1.
+
+new() ->
+ #{
+ <<"@schema">> => <<"task:1.0">>,
+ <<"id">> => ksuid:gen_id(),
+ <<"handler">> => <<"dreki_tasks_cloyster">>,
+ <<"handler_manifest">> => #{
+ <<"@schema">> => <<"cloyster-task:1.0">>,
+ <<"script">> => <<>>
+ }
+ }.
+
+schemas() ->
+ Subs = lists:foldr(fun (Handler, Acc) -> maps:merge(Acc, Handler:schemas()) end,
+ #{}, handlers()),
+ maps:merge(Subs, #{
+ default => <<"task">>,
+ <<"task">> => schemas(task)
+ }).
+
+schemas(task) ->
+ #{
+ default_version => <<"1.0">>,
+ <<"1.0">> => schemas(task, <<"1.0">>)
+ }.
+
+schemas(task, <<"1.0">>) ->
+ Handlers = handlers(),
+ Manifests0 = lists:map(fun (Handler) -> {Handler, Handler:schema_field(handler_manifest)} end, Handlers),
+ Manifests = lists:foldr(fun
+ ({Handler, undefined}, Acc) -> Acc;
+ ({Handler, Schema}, Acc) ->
+ Schemas = maps:fold(fun
+ (Atom, _, Acc) when is_atom(Atom) -> Acc;
+ (Vsn, _, Acc) -> [#{'$$ref' => <<Schema/binary, ":", Vsn/binary>>} | Acc]
+ end, [], maps:get(Schema, Handler:schemas())),
+ Acc ++ Schemas
+ end, [], Manifests0),
+
+ #{
+ version => 'draft-06',
+ title => <<"Task">>,
+ type => object,
+ properties => #{
+ id => #{type => string, <<"dreki:form">> => #{default => {ksuid, gen_id, []}}},
+ schema => #{type => string},
+ name => #{type => string, title => <<"Name">>},
+ handler => #{type => string, title => <<"Handler">>, enum => handlers()},
+ handler_manifest => #{'$ref' => <<"handler_manifest">>}
+ },
+ '$defs' => #{
+ <<"handler_manifest">> => #{anyOf => Manifests}
+ },
+ required => [handler, handler_manifest]
+ }.
+
+%% old stuff
+
+read_uri(undefined, Uri) ->
+ {ok, #{stores => #{}}};
+read_uri(Path, Uri) ->
+ case binary:split(Path, <<":">>, [global]) of
+ [<<>>, <<>>] -> {error, invalid_resource};
+ [<<>>, Id] -> {ok, #{resolve => #{kind => tasks, id => Id}}};
+ [S] -> {ok, #{store => #{kind => tasks, id => S}}};
+ [S, <<>>] -> {ok, #{store => #{kind => tasks, id => S}}};
+ [S, Id] -> {ok, #{resource => #{kind => tasks, store => S, id => Id}}};
+ R -> {error, {invalid_address, {Path, R}}}
+ end.
+
+all(Uri) when is_binary(Uri) ->
+ all(dreki_world:read_uri(Uri));
+all({ok, Uri = #{kind := tasks, uri := Uri, resource := Res = #{store := #{id := _S}}}}) ->
+ {ok, Mod, Store} = dreki_node:get_store(Uri),
+ Mod:all(Store);
+all({ok, Uri}) -> {error, unresolvable_uri, Uri};
+all(Error = {error, _}) -> Error.
+
+
+resolve(Id) ->
+ Path = dreki_world:path(),
+ case binary:match(Id, <<Path/binary, "::tasks:">>) of
+ {0,End} ->
+ StoreAndId = binary:part(Id, {End, byte_size(Id) - End}),
+ [StoreN, LId] = binary:split(StoreAndId, <<":">>),
+ {ok, {node(), StoreN, LId}}
+ end.
+
+exists({Node, StoreN, LId}) when Node =:= node() ->
+ #{mod := Mod, args := Args} = maps:get(StoreN, load_local_stores()),
+ {ok, Db} = Mod:open(Args),
+ Mod:exists(Db, LId);
+exists(N = {Node, _, _}) ->
+ erpc:call(Node, dreki_tasks, exists, [N]);
+exists(Id) when is_binary(Id) ->
+ case resolve(Id) of
+ {ok, N} -> exists(N);
+ Error = {error, _} -> Error
+ end.
+
+load_local_stores() ->
+ {ok, Val} = application:get_env(dreki, local_tasks_stores),
+ _World = #{path := Path, me := Me} = dreki_world:to_map(),
+ MapFn = fun ({Name, Mod, Args, Env}, Acc) ->
+ Store = #{local => true,
+ node => Me,
+ path => <<Path/binary, "::tasks:", Name/binary>>,
+ mod => Mod,
+ args => Args,
+ env => Env,
+ name => Name
+ },
+ maps:put(Name, Store, Acc)
+ end,
+ lists:foldr(MapFn, #{}, Val).