Skip to content

Commit fc75b84

Browse files
committed
make cfstore gen_server & introduce cfstore behaviour
1 parent a057e55 commit fc75b84

File tree

4 files changed

+348
-308
lines changed

4 files changed

+348
-308
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ clean:
2525
quick_clean:
2626
${REBAR} skip_deps=true clean
2727

28-
package:
28+
release:
2929
${REBAR} get-deps compile generate
3030

3131
run: quick

lib/cfstore/src/cfstore.erl

Lines changed: 242 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,12 @@
2323
-module(cfstore).
2424
-author("epappas").
2525

26+
-behaviour(gen_server).
27+
2628
%% API
2729
-export([
30+
start_link/2,
31+
server_info/0,
2832
create_db/1,
2933
save/2,
3034
save/3,
@@ -43,76 +47,290 @@
4347
stream_attach_done/1,
4448
stream_attachment_fetch/1]).
4549

46-
-define(CFSTORE, couch).
50+
% -define(CFSTORE, couch).
51+
52+
%% gen_server callbacks
53+
-export([init/1,
54+
handle_call/3,
55+
handle_cast/2,
56+
handle_info/2,
57+
terminate/2,
58+
code_change/3]).
59+
60+
-define(SERVER, ?MODULE).
61+
62+
-record(state, {module, last_state = {}}).
63+
64+
65+
%%%===================================================================
66+
%%% Interface functions.
67+
%%%===================================================================
68+
69+
-callback init(Args :: term()) ->
70+
{ok, StateData :: term()} | {stop, Reason :: term()}.
71+
72+
-callback handle(Resource :: any(), State :: any()) ->
73+
{Result :: any(), State :: any()}.
4774

4875
%%%===================================================================
4976
%%% API
5077
%%%===================================================================
5178

79+
-spec(start_link(Module :: term(), Args :: any()) -> {ok, Pid :: pid()} | ignore | {error, Reason :: term()}).
80+
start_link(Module, Args) -> gen_server:start_link({local, ?SERVER}, ?MODULE, [Module, Args], []).
81+
82+
-spec(server_info() -> {ok, Version :: term()}).
83+
server_info() -> gen_server:call(?MODULE, {get_info}).
84+
5285
-spec(create_db(DBName :: term()) -> {ok, DB :: term()}).
53-
create_db(DBName) -> gen_server:call(?CFSTORE, {create_db, DBName}).
86+
create_db(DBName) -> gen_server:call(?MODULE, {create_db, DBName}).
5487

5588
-spec(save(DBName :: term(), Doc :: term()) -> {ok, Doc :: term()}).
56-
save(DBName, Doc) -> gen_server:call(?CFSTORE, {save_doc, DBName, Doc}).
89+
save(DBName, Doc) -> gen_server:call(?MODULE, {save_doc, DBName, Doc}).
5790

58-
save(DBName, Doc, RefRev) ->
59-
{DocKVList} = Doc,
60-
gen_server:call(?CFSTORE, {
61-
save_doc, DBName, {lists:concat([
62-
RefRev,
63-
DocKVList
64-
])}}).
91+
save(DBName, Doc, RefRev) -> gen_server:call(?MODULE, {save_doc, DBName, Doc, RefRev}).
6592

6693
-spec(get(DBName :: term(), Ref :: term()) -> {ok, Doc :: term()}).
67-
get(DBName, Ref) -> gen_server:call(?CFSTORE, {get_doc, DBName, Ref, []}).
94+
get(DBName, Ref) -> gen_server:call(?MODULE, {get_doc, DBName, Ref, []}).
6895

6996
-spec(get(DBName :: term(), Ref :: term(), Rev :: term()) -> {ok, Doc :: term()}).
70-
get(DBName, Ref, Rev) -> gen_server:call(?CFSTORE, {get_doc, DBName, Ref, [{rev, Rev}]}).
97+
get(DBName, Ref, Rev) -> gen_server:call(?MODULE, {get_doc, DBName, Ref, [{rev, Rev}]}).
7198

7299
-spec(all(DBName :: term()) -> {ok, [Docs :: term()]}).
73-
all(DBName) -> gen_server:call(?CFSTORE, {all_docs, DBName, []}).
100+
all(DBName) -> gen_server:call(?MODULE, {all_docs, DBName, []}).
74101

75102
-spec(all(DBName :: term(), included) -> {ok, [Docs :: term()]}).
76-
all(DBName, included) -> gen_server:call(?CFSTORE, {all_docs, DBName, [include_docs]}).
103+
all(DBName, included) -> gen_server:call(?MODULE, {all_docs, DBName, [include_docs]}).
77104

78105
-spec(fetch(DBName :: term(), {DesignName :: term(), ViewName :: term()}) -> {ok, [Docs :: term()]}).
79106
fetch(DBName, {DesignName, ViewName}) ->
80-
gen_server:call(?CFSTORE, {fetch_docs, DBName, {DesignName, ViewName}, []}).
107+
gen_server:call(?MODULE, {fetch_docs, DBName, {DesignName, ViewName}, []}).
81108

82109
-spec(fetch(DBName :: term(),
83110
{DesignName :: term(), ViewName :: term()},
84111
Opts :: term()) -> {ok, [Docs :: term()]}).
85112
fetch(DBName, {DesignName, ViewName}, Opts) ->
86-
gen_server:call(?CFSTORE, {fetch_docs, DBName, {DesignName, ViewName}, Opts}).
113+
gen_server:call(?MODULE, {fetch_docs, DBName, {DesignName, ViewName}, Opts}).
87114

88115
-spec(stream(DBName :: term(),
89116
{DesignName :: term(), ViewName :: term()},
90117
{Pid :: term(), ViewFun :: term()}) -> ok).
91118
stream(DBName, {DesignName, ViewName}, {Pid, ViewFun}) ->
92-
gen_server:cast(?CFSTORE, {stream_docs, DBName, {DesignName, ViewName}, {Pid, ViewFun}}),
119+
gen_server:cast(?MODULE, {stream_docs, DBName, {DesignName, ViewName}, {Pid, ViewFun}}),
93120
ok.
94121

95122
-spec(attach(DBName :: term(), Ref :: term(),
96123
{Name :: term(), Attachment :: term()},
97124
Opts :: term()) -> {ok, Result :: term()}).
98125
attach(DBName, Ref, {Name, Attachment}, Opts) ->
99-
gen_server:call(?CFSTORE, {attach_doc, DBName, Ref, {Name, Attachment}, Opts}).
126+
gen_server:call(?MODULE, {attach_doc, DBName, Ref, {Name, Attachment}, Opts}).
100127

101128
stream_attach(Ref, Msg) ->
102-
gen_server:call(?CFSTORE, {stream_attach, Ref, Msg}).
129+
gen_server:call(?MODULE, {stream_attach, Ref, Msg}).
103130

104131
stream_attach_done(Ref) ->
105-
gen_server:call(?CFSTORE, {stream_attach, Ref, eof}).
132+
gen_server:call(?MODULE, {stream_attach, Ref, eof}).
106133

107134
stream_attachment_fetch(Ref) ->
108-
gen_server:call(?CFSTORE, {stream_attachment, Ref}).
135+
gen_server:call(?MODULE, {stream_attachment, Ref}).
109136

110137
-spec(fetch_attachment(DBName :: term(), Ref :: term(), Name :: term()) ->
111138
{ok, Attachment :: term()}).
112-
fetch_attachment(DBName, Ref, Name) -> gen_server:call(?CFSTORE, {fetch_attachment, DBName, Ref, Name}).
139+
fetch_attachment(DBName, Ref, Name) -> gen_server:call(?MODULE, {fetch_attachment, DBName, Ref, Name}).
113140

114-
fetch_attachment_stream(DBName, Ref, Name) -> gen_server:call(?CFSTORE, {fetch_attachment_stream, DBName, Ref, Name}).
141+
fetch_attachment_stream(DBName, Ref, Name) -> gen_server:call(?MODULE, {fetch_attachment_stream, DBName, Ref, Name}).
115142

116143
-spec(drop_attachment(DBName :: term(), Ref :: term(), Name :: term()) -> ok).
117-
drop_attachment(DBName, Ref, Name) -> gen_server:cast(?CFSTORE, {drop_attachment, DBName, Ref, Name}),
144+
drop_attachment(DBName, Ref, Name) -> gen_server:cast(?MODULE, {drop_attachment, DBName, Ref, Name}),
118145
ok.
146+
147+
%%%===================================================================
148+
%%% gen_server callbacks
149+
%%%===================================================================
150+
151+
%%--------------------------------------------------------------------
152+
%% @private
153+
%% @doc
154+
%% Initializes the server
155+
%%
156+
%% @spec init(Args) -> {ok, State} |
157+
%% {ok, State, Timeout} |
158+
%% ignore |
159+
%% {stop, Reason}
160+
%% @end
161+
%%--------------------------------------------------------------------
162+
-spec(init(Args :: term()) ->
163+
{ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} |
164+
{stop, Reason :: term()} | ignore).
165+
166+
init([Module, Args]) ->
167+
{ok, LastState} = Module:init(Args),
168+
{ok, #state{module = Module, last_state = LastState}}.
169+
170+
%%--------------------------------------------------------------------
171+
%% @private
172+
%% @doc
173+
%% Create a DB (or just Open it)
174+
%%
175+
%% @end
176+
%%--------------------------------------------------------------------
177+
-spec(handle_call(Request :: term(), From :: {pid(), Tag :: term()},
178+
State :: #state{}) ->
179+
{reply, {ok, DB :: term()}, NewState :: #state{}}).
180+
handle_call({create_db, DBName}, _From, #state{module = Module, last_state = LastState}) ->
181+
{Reply, NewState} = Module:handle({create_db, DBName}, LastState),
182+
{reply, Reply, #state{module = Module, last_state = NewState}};
183+
184+
%%--------------------------------------------------------------------
185+
%% @private
186+
%% @doc
187+
%% Save a Doc to a DB
188+
%%
189+
%% @end
190+
%%--------------------------------------------------------------------
191+
handle_call({save_doc, DBName, Doc}, _From, #state{module = Module, last_state = LastState}) ->
192+
{Reply, NewState} = Module:handle({save_doc, DBName, Doc}, LastState),
193+
{reply, Reply, #state{module = Module, last_state = NewState}};
194+
195+
%%--------------------------------------------------------------------
196+
%% @private
197+
%% @doc
198+
%% GET a Doc by ref from a DB
199+
%%
200+
%% @end
201+
%%--------------------------------------------------------------------
202+
handle_call({get_doc, DBName, Ref, Options}, _From, #state{module = Module, last_state = LastState}) ->
203+
{Reply, NewState} = Module:handle({get_doc, DBName, Ref, Options}, LastState),
204+
{reply, Reply, #state{module = Module, last_state = NewState}};
205+
206+
%%--------------------------------------------------------------------
207+
%% @private
208+
%% @doc
209+
%% LIST all Docs from a DB
210+
%%
211+
%% @end
212+
%%--------------------------------------------------------------------
213+
handle_call({all_docs, DBName, Options}, _From, #state{module = Module, last_state = LastState}) ->
214+
{Reply, NewState} = Module:handle({all_docs, DBName, Options}, LastState),
215+
{reply, Reply, #state{module = Module, last_state = NewState}};
216+
217+
%%--------------------------------------------------------------------
218+
%% @private
219+
%% @doc
220+
%% LIST Docs from a view of a DB
221+
%%
222+
%% @end
223+
%%--------------------------------------------------------------------
224+
handle_call({fetch_docs, DBName, {DesignName, ViewName}, Options}, _From, #state{module = Module, last_state = LastState}) ->
225+
{Reply, NewState} = Module:handle({fetch_docs, DBName, {DesignName, ViewName}, Options}, LastState),
226+
{reply, Reply, #state{module = Module, last_state = NewState}};
227+
228+
%%--------------------------------------------------------------------
229+
%% @private
230+
%% @doc
231+
%% Set an Attachment to a Doc
232+
%%
233+
%% @end
234+
%%--------------------------------------------------------------------
235+
handle_call({attach_doc, DBName, Ref, {Name, Attachment}, Options}, _From, #state{module = Module, last_state = LastState}) ->
236+
{Reply, NewState} = Module:handle({attach_doc, DBName, Ref, {Name, Attachment}, Options}, LastState),
237+
{reply, Reply, #state{module = Module, last_state = NewState}};
238+
239+
%%--------------------------------------------------------------------
240+
%% @private
241+
%% @doc
242+
%% stream an Attachment
243+
%%
244+
%% @end
245+
%%--------------------------------------------------------------------
246+
handle_call({stream_attach, Ref, Msg}, _From, #state{module = Module, last_state = LastState}) ->
247+
{Reply, NewState} = Module:handle({stream_attach, Ref, Msg}, LastState),
248+
{reply, Reply, #state{module = Module, last_state = NewState}};
249+
250+
handle_call({stream_attachment, Ref}, _From, #state{module = Module, last_state = LastState}) ->
251+
{Reply, NewState} = Module:handle({stream_attachment, Ref}, LastState),
252+
{reply, Reply, #state{module = Module, last_state = NewState}};
253+
254+
%%--------------------------------------------------------------------
255+
%% @private
256+
%% @doc
257+
%% fetch an Attachment from a Doc
258+
%%
259+
%% @end
260+
%%--------------------------------------------------------------------
261+
handle_call({fetch_attachment, DBName, Ref, Name}, _From, #state{module = Module, last_state = LastState}) ->
262+
{Reply, NewState} = Module:handle({fetch_attachment, DBName, Ref, Name}, LastState),
263+
{reply, Reply, #state{module = Module, last_state = NewState}};
264+
265+
%%--------------------------------------------------------------------
266+
%% @private
267+
%% @doc
268+
%% Stream an Attachment from a Doc
269+
%%
270+
%% @end
271+
%%--------------------------------------------------------------------
272+
handle_call({fetch_attachment_stream, DBName, Ref, Name}, _From, #state{module = Module, last_state = LastState}) ->
273+
{Reply, NewState} = Module:handle({fetch_attachment_stream, DBName, Ref, Name}, LastState),
274+
{reply, Reply, #state{module = Module, last_state = NewState}}.
275+
276+
%%--------------------------------------------------------------------
277+
%% @private
278+
%% @doc
279+
%% Handle Streamed rows
280+
%%
281+
%% @end
282+
%%--------------------------------------------------------------------
283+
handle_cast({stream_docs, DBName, {DesignName, ViewName}, {Pid, ViewFun}}, #state{module = Module, last_state = LastState}) ->
284+
{_Reply, NewState} = Module:handle({stream_docs, DBName, {DesignName, ViewName}, {Pid, ViewFun}}, LastState),
285+
{noreply, #state{module = Module, last_state = NewState}};
286+
287+
handle_cast({drop_attachment, DBName, Ref, Name}, #state{module = Module, last_state = LastState}) ->
288+
{_Reply, NewState} = Module:handle({drop_attachment, DBName, Ref, Name}, LastState),
289+
{noreply, #state{module = Module, last_state = NewState}};
290+
291+
handle_cast(_Request, State) -> {noreply, State}.
292+
293+
%%--------------------------------------------------------------------
294+
%% @private
295+
%% @doc
296+
%% Handling all non call/cast messages
297+
%%
298+
%% @spec handle_info(Info, State) -> {noreply, State} |
299+
%% {noreply, State, Timeout} |
300+
%% {stop, Reason, State}
301+
%% @end
302+
%%--------------------------------------------------------------------
303+
-spec(handle_info(Info :: timeout() | term(), State :: #state{}) ->
304+
{noreply, NewState :: #state{}} |
305+
{noreply, NewState :: #state{}, timeout() | hibernate} |
306+
{stop, Reason :: term(), NewState :: #state{}}).
307+
handle_info(_Info, State) ->
308+
{noreply, State}.
309+
310+
%%--------------------------------------------------------------------
311+
%% @private
312+
%% @doc
313+
%% This function is called by a gen_server when it is about to
314+
%% terminate. It should be the opposite of Module:init/1 and do any
315+
%% necessary cleaning up. When it returns, the gen_server terminates
316+
%% with Reason. The return value is ignored.
317+
%%
318+
%% @spec terminate(Reason, State) -> void()
319+
%% @end
320+
%%--------------------------------------------------------------------
321+
-spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()),
322+
State :: #state{}) -> term()).
323+
terminate(_Reason, _State) -> ok.
324+
325+
%%--------------------------------------------------------------------
326+
%% @private
327+
%% @doc
328+
%% Convert process state when code is changed
329+
%%
330+
%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
331+
%% @end
332+
%%--------------------------------------------------------------------
333+
-spec(code_change(OldVsn :: term() | {down, term()}, State :: #state{}, Extra :: term()) ->
334+
{ok, NewState :: #state{}} | {error, Reason :: term()}).
335+
code_change(_OldVsn, State, _Extra) ->
336+
{ok, State}.

lib/cfstore/src/cfstore_sup.erl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ init_couch_engine(Application) ->
7373
end,
7474
CouchOpts = application:get_env(Application, couch_opts, []),
7575

76-
{couch,
77-
{couch, start_link, [CouchUrl, CouchOpts]},
76+
{cfstore,
77+
{cfstore, start_link, [couch, [CouchUrl, CouchOpts]]},
7878
permanent, 1000, worker,
79-
[couch]}.
79+
[cfstore]}.

0 commit comments

Comments
 (0)