Skip to content

Commit

Permalink
Re-apply saved bookings
Browse files Browse the repository at this point in the history
  • Loading branch information
grahamrhay committed Jan 4, 2024
1 parent 8b88e49 commit ef414e6
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 11 deletions.
34 changes: 24 additions & 10 deletions apps/cqrs_booking/src/cqrs_booking.erl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

-behaviour(gen_server).

-export([ init/1 , handle_call/3 , handle_cast/2 , handle_info/2, handle_continue/2 ]).
-export([ init/1 , handle_call/3 , handle_cast/2 , handle_info/2, handle_continue/2, terminate/2 ]).

-include_lib("stdlib/include/ms_transform.hrl").

-type state() :: #{}.

Expand All @@ -16,18 +18,23 @@ start_link() ->

-spec init(unused) -> {ok, state()}.
init(unused) ->
Version = 0,
State = #{
available_rooms => cqrs_booking_hotels:get_available_rooms(),
bookings => #{},
version => 0
version => Version
},
{ok, _Name} = dets:open_file(bookings, []),
{ok, State}.
MatchSpec = ets:fun2ms(fun({N,Cmd}) when N >= Version -> {N, Cmd} end),
ExistingBookings = lists:sort(fun({A,_}, {B,_}) -> A =< B end, dets:select(bookings, MatchSpec)),
io:format("Existing bookings: ~p~n", [ExistingBookings]),
NewBookings = lists:foldl(fun({_, Cmd}, B) -> add_new_booking(Cmd, B) end, maps:get(bookings, State), ExistingBookings),
{ok, State#{bookings:=NewBookings, version:=Version + length(ExistingBookings)}}.

-spec handle_call(any(), {pid(), any()}, state()) ->
{reply, any(), state()} | {noreply, state()}.
handle_call({book_room, Cmd}, _From, #{available_rooms:=AvailableRooms, version:=Version} = State) ->
{Client, Hotel, Room, CheckIn, _CheckOut} = Cmd,
{_Client, Hotel, Room, CheckIn, _CheckOut} = Cmd,
AvailableRoomsForHotel = maps:get(Hotel, AvailableRooms),
AvailableRoomsForDay = maps:get(CheckIn, AvailableRoomsForHotel),
[_RoomInfo] = lists:filter(fun(R) -> maps:get(id, R) == Room end, AvailableRoomsForDay),
Expand All @@ -50,14 +57,21 @@ handle_info(_Request, State) ->
{noreply, State}.

-spec handle_continue(term(), state()) -> {noreply, state()}.
handle_continue({new_booking, {Client, _Hotel, _Room, _CheckIn, _CheckOut} = Cmd}, #{bookings:=Bookings} = State) ->
NewBookings = case maps:is_key(Client, Bookings) of
handle_continue({new_booking, Cmd}, #{bookings:=Bookings} = State) ->
NewBookings = add_new_booking(Cmd, Bookings),
{noreply, State#{bookings:=NewBookings}};
handle_continue(_Continue, State) ->
{noreply, State}.

terminate(_Reason, _State) ->
dets:close(bookings),
ok.

add_new_booking({Client, _Hotel, _Room, _CheckIn, _CheckOut} = Cmd, Bookings) ->
case maps:is_key(Client, Bookings) of
true ->
BookingsForClient = maps:get(Client, Bookings),
maps:update(Client, [Cmd | BookingsForClient], Bookings);
false ->
maps:put(Client, [Cmd], Bookings)
end,
{noreply, State#{bookings:=NewBookings}};
handle_continue(_Continue, State) ->
{noreply, State}.
end.
27 changes: 26 additions & 1 deletion apps/cqrs_booking/test/cqrs_booking_tests.erl
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ init_test_() ->
].

init_available_rooms() ->
clean_dets_files(),
{ok, #{available_rooms:=AvailableRooms}} = cqrs_booking:init(unused),
cqrs_booking:terminate(shutdown, #{}),
?_assertEqual(AvailableRooms, cqrs_booking_hotels:get_available_rooms()).

init_bookings_list_is_empty() ->
clean_dets_files(),
{ok, #{bookings:=Bookings}} = cqrs_booking:init(unused),
cqrs_booking:terminate(shutdown, #{}),
?_assertEqual(0, length(maps:keys(Bookings))).

handle_call_test_() ->
Expand All @@ -22,12 +26,21 @@ handle_call_test_() ->
unavailable_room_cannot_be_booked()
].

restore_test_() ->
[
bookings_should_survive_restart()
].

start() ->
clean_dets_files(),
{ok, Pid} = cqrs_booking:start_link(),
Pid.

clean_dets_files() ->
ok = case file:delete("bookings") of ok -> ok; {error, enoent} -> ok end.

stop(Pid) ->
gen_server:stop(Pid).
ok = gen_server:stop(Pid).

new_booking_should_be_added(Pid) ->
Client = 1,
Expand All @@ -50,3 +63,15 @@ new_state() ->
bookings => #{},
version => 0
}.

bookings_should_survive_restart() ->
Pid1 = start(),
Client = 1,
Cmd = {Client, 2, <<"101">>, {2023, 12, 1}, {2023, 12, 2}},
ok = gen_server:call(Pid1, {book_room, Cmd}),
stop(Pid1),
{ok, Pid2} = cqrs_booking:start_link(),
{ok, BookingsForClient} = gen_server:call(Pid2, {get_bookings, Client}),
[
?_assertEqual(1, length(BookingsForClient))
].

0 comments on commit ef414e6

Please sign in to comment.