diff options
Diffstat (limited to 'apps/dreki/src/dreki_tasks.erl')
-rw-r--r-- | apps/dreki/src/dreki_tasks.erl | 141 |
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). |