aboutsummaryrefslogtreecommitdiff
path: root/apps/dreki/src/dreki_dets_tasks.erl
blob: 9b798ef77d0ce4108c58c81e6235cb14b79b5709 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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.