diff options
Diffstat (limited to 'apps/dreki/src/dreki_dets_tasks.erl')
-rw-r--r-- | apps/dreki/src/dreki_dets_tasks.erl | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/apps/dreki/src/dreki_dets_tasks.erl b/apps/dreki/src/dreki_dets_tasks.erl new file mode 100644 index 0000000..9b798ef --- /dev/null +++ b/apps/dreki/src/dreki_dets_tasks.erl @@ -0,0 +1,90 @@ +-module(dreki_dets_tasks). +-include("dreki.hrl"). + +%% Types +-type db() :: term(). +-type args() :: #{db_name => binary()}. + +%% storage-specific +-export([start/1, open/1, sync/1, close/1, stop/1]). +-export([checkout/1, checkin/1]). +-export([list/1, count/1, exists/2, get/2, create/2, update/2, delete/2]). + +-define(DETS, dreki_tasks_dets). + +dets_name(_Args = #{store_name := StoreName}) when is_binary(StoreName) -> + {dreki_dets_tasks, StoreName}. + +file_name(_Args = #{file_name := FileName}) when is_binary(FileName) -> + binary:bin_to_list(FileName); +file_name(_Args = #{store_name := StoreName}) when is_binary(StoreName) -> + File = <<"tasks.", StoreName/binary, ".dets">>, + binary:bin_to_list(File). + +-spec start(args()) -> {ok, db()} | {error, Reason::term()}. +start(Args) -> + dets:open_file(dets_name(Args), [{file, file_name(Args)}, {keypos, 2}]). + +-spec open(args()) -> {ok, db()} | {error, Reason::term()}. +open(Args) -> + start(Args). + +-spec close(db()) -> ok | {error, Reason::term()}. +close(Tab) -> + dets:close(Tab). + +-spec stop(args()) -> ok | {error, Reason::term()}. +stop(Args) -> + Tab = dets_name(Args), + dets:close(Tab). + +sync(Tab) -> + dets:sync(Tab). + +checkout(Args) -> + start(Args). + +checkin(Tab) -> + dets:close(Tab). + +-spec list(db()) -> {ok, [dreki_task()]} | {error, Reason::term()}. +list(Tab) -> + dets:foldl(fun (T, {ok, Ts}) -> {ok, [T | Ts]} end, {ok, []}, Tab). + +-spec count(db()) -> {ok, Count::non_neg_integer()} | {error, Reason::term()}. +count(Tab) -> + dets:foldl(fun (_T, {ok, Ct}) -> {ok, Ct + 1} end, {ok, 0}, Tab). + +-spec exists(db(), dreki_id()) -> boolean. +exists(Tab, Id) -> + dets:member(Tab, Id). + +-spec get(db(), dreki_id()) -> {ok, dreki_task()} | {error, {task_not_found, dreki_id()}}. +get(Tab, Id) -> + case dets:lookup(Tab, Id) of + [] -> {error, {task_not_found, Id}}; + [Task] -> {ok, Task} + end. + +-spec delete(db(), dreki_id()) -> ok | {error, Reason::term()}. +delete(Tab, Id) -> + dets:delete(Tab, Id). + +-spec create(db(), dreki_task()) -> {ok, dreki_task()} | {error, Reason::term()}. +create(Tab, Task = #dreki_task{persisted=false}) -> + case dets:insert_new(Tab, Task#dreki_task{persisted=true, dirty=false}) of + true -> {ok, Task#dreki_task{persisted=true, dirty=false}}; + false -> {error, {task_exists, Task#dreki_task.id}}; + {error, Error} -> {error, Error} + end. + +-spec update(db(), dreki_task()) -> {ok, dreki_task()} | {error, Reason::term()}. +update(_Tab, Task = #dreki_task{persisted=false}) -> + {error, {task_not_created, Task#dreki_task.id}}; +update(_Tab, Task = #dreki_task{dirty=false}) -> + {ok, Task}; +update(Tab, Task = #dreki_task{persisted=true, dirty=true}) -> + case dets:insert(Tab, Task#dreki_task{dirty=false}) of + ok -> {ok, Task#dreki_task{dirty=false}}; + {error, Error} -> {error, Error} + end. |