diff --git a/src/fd_sfc.erl b/src/fd_sfc.erl new file mode 100644 index 0000000..dc38007 --- /dev/null +++ b/src/fd_sfc.erl @@ -0,0 +1,108 @@ +% @doc static file cache +-module(fd_sfc). + +-behavior(gen_server). + +-export([ + %% caller context + start_link/0, + + %% process context + init/1, handle_call/3, handle_cast/2, handle_info/2, + code_change/3, terminate/2 +]). + +-include("$zx_include/zx_logger.hrl"). + +-record(e, {fs_path :: file:filename(), + last_modified :: file:date_time(), + mime_type :: string(), + contents :: binary()}). + +-type entry() :: #e{}. + +-record(s, {entries = #{ :: [entry()]}). + +-type state() :: #s{}. + + + + +start_link() -> + gen_server:start_link({local, ?MODULE}, ?MODULE, none, []). + + +%%----------------------------------------------------------------------------- +%% process context below this line +%%----------------------------------------------------------------------------- + +%% gen_server callbacks + +init(none) -> + log(info, "starting fd_cache"), + InitState = #s{}, + {ok, InitState}. + + +handle_call(Unexpected, From, State) -> + tell("~tp: unexpected call from ~tp: ~tp", [?MODULE, Unexpected, From]), + {noreply, State}. + + +handle_cast(Unexpected, State) -> + tell("~tp: unexpected cast: ~tp", [?MODULE, Unexpected]), + {noreply, State}. + + +handle_info(Unexpected, State) -> + tell("~tp: unexpected info: ~tp", [?MODULE, Unexpected]), + {noreply, State}. + + +code_change(_, State, _) -> + {ok, State}. + +terminate(_, _) -> + ok. + + +%%--------------------- +%% doers +%%--------------------- + + +-spec refresh_entry(Entry) -> Result + when Entry :: entry(), + Result :: {found, NewEntry :: entry()} + | not_found. + +refresh_entry(Entry) -> + refresh_entry(Entry, false). + + +-spec refresh_entry(Entry, Force) -> Result + when Entry :: entry(), + Force :: boolean(), + Result :: {found, NewEntry :: entry()} + | not_found. +% @private +% Force = even if file has not been modified, still refresh contents + +refresh_entry(E = #e{fs_path = Path}, Force) -> + case file:find_file(Path) of + {ok, _} -> re2(E, Force); + {error, not_found} -> not_found. + end. + +re2(E = #e{fs_path = Path, last_modified = LastModified}, _Force = false) -> + case file:last_modified(Path) > LastModified of + false -> {found, E}; + true -> re2(E, true) + end; +re2(E = #e{http_path = HttpPath}, _Force = true) -> + new_entry(HttpPath). + + +-spec new_entry(HttpPath) -> Result + when HttpPath :: binary(), + FilePath :: diff --git a/src/fd_sfc_entry.erl b/src/fd_sfc_entry.erl new file mode 100644 index 0000000..b726b60 --- /dev/null +++ b/src/fd_sfc_entry.erl @@ -0,0 +1,2 @@ +% @doc non-servery functions for static file caching +-module(fd_sfc_entry) diff --git a/src/fd_static_cache.erl b/src/fd_static_cache.erl deleted file mode 100644 index 5c3985f..0000000 --- a/src/fd_static_cache.erl +++ /dev/null @@ -1,125 +0,0 @@ -% @doc static file cache --module(fd_static_cache). - --behavior(gen_server). - --export([ - start_link/0, - query/1, set/2, unset/1, - %%--- - %% everything below here runs in process context - %%-- - %% gen_server callbacks - init/1, handle_call/3, handle_cast/2, handle_info/2, - code_change/3, terminate/2 -]). - --include("$zx_include/zx_logger.hrl"). - --record(f, {http_path :: binary(), - fs_path :: file:filename(), - last_modified :: file:date_time(), - mime_type :: string(), - contents :: binary()}). --type context() :: wfc_eval_context:context(). - --record(s, - {cookies = #{} :: #{Cookie :: binary() := context()}}). -% -type state() :: #s{}. - - -%%-------------------------------- -%% api (runs in context of caller) -%%-------------------------------- - --spec start_link() -> {ok, pid()} | {error, term()}. -start_link() -> - gen_server:start_link({local, ?MODULE}, ?MODULE, none, []). - - - --spec query(Cookie) -> {ok, Context} | error - when Cookie :: binary(), - Context :: context(). - -query(Cookie) -> - gen_server:call(?MODULE, {query, Cookie}). - - - --spec set(Cookie, Context) -> ok - when Cookie :: binary(), - Context :: context(). - -set(Cookie, Context) -> - gen_server:cast(?MODULE, {set, Cookie, Context}). - - --spec unset(Cookie) -> ok - when Cookie :: binary(). - -unset(Cookie) -> - gen_server:cast(?MODULE, {unset, Cookie}). - - -%%---------------------- -%% gen-server bs -%%---------------------- - - - -init(none) -> - log(info, "starting fd_cache"), - InitState = #s{}, - {ok, InitState}. - - -handle_call({query, Cookie}, _, State) -> - Result = do_query(Cookie, State), - {reply, Result, State}; -handle_call(Unexpected, From, State) -> - tell("~tp: unexpected call from ~tp: ~tp", [?MODULE, Unexpected, From]), - {noreply, State}. - - -handle_cast({set, Cookie, Context}, State) -> - NewState = do_set(Cookie, Context, State), - {noreply, NewState}; -handle_cast({unset, Cookie}, State) -> - NewState = do_unset(Cookie, State), - {noreply, NewState}; -handle_cast(Unexpected, State) -> - tell("~tp: unexpected cast: ~tp", [?MODULE, Unexpected]), - {noreply, State}. - - -handle_info(Unexpected, State) -> - tell("~tp: unexpected info: ~tp", [?MODULE, Unexpected]), - {noreply, State}. - - -code_change(_, State, _) -> - {ok, State}. - -terminate(_, _) -> - ok. - - -%%--------------------- -%% doers -%%--------------------- - -do_set(Cookie, Context, State = #s{cookies = Cookies}) -> - NewCookies = maps:put(Cookie, Context, Cookies), - NewState = State#s{cookies = NewCookies}, - NewState. - - -do_unset(Cookie, State = #s{cookies = Cookies}) -> - NewCookies = maps:remove(Cookie, Cookies), - NewState = State#s{cookies = NewCookies}, - NewState. - - -do_query(Cookie, _State = #s{cookies = Cookies}) -> - maps:find(Cookie, Cookies).