Skip to content
This repository has been archived by the owner on May 2, 2023. It is now read-only.

Commit

Permalink
implement concurrent drivers for greater throughput (#215)
Browse files Browse the repository at this point in the history
* use pool of drivers to increase concurrency

* improve error logging

* update antidote docker image

* update deps, small tweaks to drivers

* remove unsupported drivers

* fix bugs in adapter and ets driver

* update erlang release to be used in travis

* delete obsolete modules
  • Loading branch information
goncalotomas authored Jul 17, 2019
1 parent 5ffdcab commit eed698c
Show file tree
Hide file tree
Showing 31 changed files with 530 additions and 2,046 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
dist: xenial
language: erlang
otp_release:
- 21.1
- 22.0
services:
- docker
addons:
Expand Down
12 changes: 3 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,23 @@ coverage: eunit ct
${REBAR} cover --verbose

ct:
${REBAR} ct --cover
${REBAR} ct --suite fmke_antidote_transactions_SUITE.erl --cover --cover_export_name=antidote_txn_check
${REBAR} ct --suite fmke_db_conn_manager_SUITE.erl --cover --cover_export_name=db_conn_manager
${REBAR} ct --suite fmke_unstable_db_conn_SUITE.erl --cover --cover_export_name=unstable_db_conn
${REBAR} ct --suite fmke_core_unit_test_SUITE.erl --config test/fmke_configs/antidote_non_nested_data_model.config --cover --cover_export_name=core_antidote_non_nested_opt
${REBAR} ct --suite fmke_core_unit_test_SUITE.erl --config test/fmke_configs/cassandra_non_nested_data_model.config --cover --cover_export_name=core_cassandra_non_nested_opt
${REBAR} ct --suite fmke_core_unit_test_SUITE.erl --config test/fmke_configs/ets_nested_data_model.config --cover --cover_export_name=core_ets_nested
${REBAR} ct --suite fmke_core_unit_test_SUITE.erl --config test/fmke_configs/ets_non_nested_data_model.config --cover --cover_export_name=core_ets_non_nested
${REBAR} ct --suite fmke_core_unit_test_SUITE.erl --config test/fmke_configs/redis_cluster_non_nested_data_model.config --cover --cover_export_name=core_redis_cluster_non_nested_opt
${REBAR} ct --suite fmke_core_unit_test_SUITE.erl --config test/fmke_configs/redis_crdb_non_nested_data_model.config --cover --cover_export_name=core_redis_crdb_non_nested_opt
${REBAR} ct --suite fmke_core_unit_test_SUITE.erl --config test/fmke_configs/riak_non_nested_data_model.config --cover --cover_export_name=core_riak_non_nested_opt
${REBAR} ct --suite fmke_core_unit_test_SUITE.erl --config test/fmke_configs/riak_simple_nested.config --cover --cover_export_name=core_riak_simple_nested
${REBAR} ct --suite fmke_core_unit_test_SUITE.erl --config test/fmke_configs/riak_simple_non_nested.config --cover --cover_export_name=core_riak_simple_non_nested
${REBAR} ct --suite fmke_http_api_SUITE.erl --config test/fmke_configs/antidote_non_nested_data_model.config --cover --cover_export_name=http_antidote_non_nested_opt
${REBAR} ct --suite fmke_http_api_SUITE.erl --config test/fmke_configs/cassandra_non_nested_data_model.config --cover --cover_export_name=http_cassandra_non_nested_opt
${REBAR} ct --suite fmke_http_api_SUITE.erl --config test/fmke_configs/ets_nested_data_model.config --cover --cover_export_name=http_ets_nested
${REBAR} ct --suite fmke_http_api_SUITE.erl --config test/fmke_configs/ets_non_nested_data_model.config --cover --cover_export_name=http_ets_non_nested
${REBAR} ct --suite fmke_http_api_SUITE.erl --config test/fmke_configs/redis_cluster_non_nested_data_model.config --cover --cover_export_name=http_redis_cluster_non_nested_opt
${REBAR} ct --suite fmke_http_api_SUITE.erl --config test/fmke_configs/redis_crdb_non_nested_data_model.config --cover --cover_export_name=http_redis_crdb_non_nested_opt
${REBAR} ct --suite fmke_http_api_SUITE.erl --config test/fmke_configs/riak_non_nested_data_model.config --cover --cover_export_name=http_riak_non_nested_opt
${REBAR} ct --suite fmke_http_api_SUITE.erl --config test/fmke_configs/riak_simple_nested.config --cover --cover_export_name=http_riak_simple_nested
${REBAR} ct --suite fmke_http_api_SUITE.erl --config test/fmke_configs/riak_simple_non_nested.config --cover --cover_export_name=http_riak_simple_non_nested

ct-antidote:
${REBAR} ct --suite fmke_core_unit_test_SUITE.erl --config test/fmke_configs/antidote_non_nested_data_model.config
Expand All @@ -64,11 +62,7 @@ ct-redis:

ct-riak:
${REBAR} ct --suite fmke_core_unit_test_SUITE.erl --config test/fmke_configs/riak_non_nested_data_model.config
${REBAR} ct --suite fmke_core_unit_test_SUITE.erl --config test/fmke_configs/riak_simple_nested.config
${REBAR} ct --suite fmke_core_unit_test_SUITE.erl --config test/fmke_configs/riak_simple_non_nested.config
${REBAR} ct --suite fmke_http_api_SUITE.erl --config test/fmke_configs/riak_non_nested_data_model.config
${REBAR} ct --suite fmke_http_api_SUITE.erl --config test/fmke_configs/riak_simple_nested.config
${REBAR} ct --suite fmke_http_api_SUITE.erl --config test/fmke_configs/riak_simple_non_nested.config

dialyzer:
${REBAR} dialyzer
Expand Down
2 changes: 1 addition & 1 deletion config/vm.args
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
-setcookie ${COOKIE}

## Directories with compiled modules
-pa ./_build/default/lib/*/ebin
-pa ./_build/default/lib/*/ebin releases/${REL_VSN}/consolidated
2 changes: 1 addition & 1 deletion elvis.config
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
{elvis_style, god_modules, #{limit => 30, ignore => []}},
{elvis_style, no_if_expression},
{elvis_style, invalid_dynamic_call, #{ignore => [
fmke, fmke_db_connection, fmke_pt_adapter, fmke_kv_adapter
fmke, fmke_db_connection, fmke_kv_adapter
]}},
{elvis_style, used_ignored_variable},
{elvis_style, no_behavior_info},
Expand Down
6 changes: 4 additions & 2 deletions include/fmke.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,15 @@
-type field() :: binary().
-type reason() :: term().
-type crdt() :: term().
-type key() :: binary().
-type app_record() :: #facility{} |
#patient{} |
#pharmacy{} |
#prescription{} |
#staff{}.
#staff{} |
list(key()).

-type entity() :: facility | patient | pharmacy | prescription | staff.
-type key() :: binary().

-type facility() :: #facility{}.
-type patient() :: #patient{}.
Expand Down
3 changes: 2 additions & 1 deletion rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
%% Cassandra
{erlcass, "~>3.2"},
%% Redis Cluster
{eredis_cluster, "~>0.5"},
{eredis_cluster, {git, "https://github.com/adrienmo/eredis_cluster", {tag, "0.5.12"}}},
%% Riak KV
{riak_client, "~>2.5"}
]}.


{eunit_opts, [
verbose,
{report, {eunit_surefire, [{dir,"."}]}}
Expand Down
46 changes: 24 additions & 22 deletions rebar.lock
Original file line number Diff line number Diff line change
@@ -1,34 +1,36 @@
{"1.1.0",
[{<<"antidote_pb_codec">>,{pkg,<<"antidote_pb_codec">>,<<"0.0.3">>},1},
{<<"antidotec_pb">>,{pkg,<<"antidotec_pb">>,<<"0.2.4">>},0},
{<<"cowboy">>,{pkg,<<"cowboy">>,<<"2.4.0">>},0},
{<<"cowlib">>,{pkg,<<"cowlib">>,<<"2.3.0">>},1},
{<<"eredis">>,{pkg,<<"eredis">>,<<"1.1.0">>},1},
{<<"eredis_cluster">>,{pkg,<<"eredis_cluster">>,<<"0.5.11">>},0},
{<<"erlcass">>,{pkg,<<"erlcass">>,<<"3.2.3">>},0},
[{<<"antidote_pb_codec">>,{pkg,<<"antidote_pb_codec">>,<<"0.1.1">>},1},
{<<"antidotec_pb">>,{pkg,<<"antidotec_pb">>,<<"0.2.8">>},0},
{<<"cowboy">>,{pkg,<<"cowboy">>,<<"2.6.3">>},0},
{<<"cowlib">>,{pkg,<<"cowlib">>,<<"2.7.3">>},1},
{<<"eredis">>,{pkg,<<"eredis">>,<<"1.2.0">>},1},
{<<"eredis_cluster">>,
{git,"https://github.com/adrienmo/eredis_cluster",
{ref,"69dd345867bd14353890c559ed07820e6c001ef2"}},
0},
{<<"erlcass">>,{pkg,<<"erlcass">>,<<"3.2.4">>},0},
{<<"goldrush">>,{pkg,<<"goldrush">>,<<"0.1.9">>},1},
{<<"hamcrest">>,{pkg,<<"basho_hamcrest">>,<<"0.4.1">>},2},
{<<"jsx">>,{pkg,<<"jsx">>,<<"2.9.0">>},0},
{<<"lager">>,{pkg,<<"lager">>,<<"3.6.6">>},0},
{<<"poolboy">>,{pkg,<<"poolboy">>,<<"1.5.1">>},0},
{<<"ranch">>,{pkg,<<"ranch">>,<<"1.5.0">>},1},
{<<"jsx">>,{pkg,<<"jsx">>,<<"2.10.0">>},0},
{<<"lager">>,{pkg,<<"lager">>,<<"3.7.0">>},0},
{<<"poolboy">>,{pkg,<<"poolboy">>,<<"1.5.2">>},0},
{<<"ranch">>,{pkg,<<"ranch">>,<<"1.7.1">>},1},
{<<"riak_client">>,{pkg,<<"riak_client">>,<<"2.5.3">>},0},
{<<"riak_pb">>,{pkg,<<"riak_pb">>,<<"2.3.2">>},1}]}.
[
{pkg_hash,[
{<<"antidote_pb_codec">>, <<"692A14320C6A78E5906E4EF182D5C09C0BC0CDEFCB3C09338C08FECA3F0226CB">>},
{<<"antidotec_pb">>, <<"9B6A760D75AFF0BCFC6B136DE6E4065B4FB4AED5D6AF18246FDC5B8F7F64C12F">>},
{<<"cowboy">>, <<"F1B72FABE9C8A5FC64AC5AC85FB65474D64733D1DF52A26FAD5D4BA3D9F70A9F">>},
{<<"cowlib">>, <<"BBD58EF537904E4F7C1DD62E6AA8BC831C8183CE4EFA9BD1150164FE15BE4CAA">>},
{<<"eredis">>, <<"8D8D74496F35216679B97726B75FB1C8715E99DD7F3EF9F9824A2264C3E0AAC0">>},
{<<"eredis_cluster">>, <<"383E44C47B4DF06145448680D84BBC95A7E8CD708E9100BEB0E461ECFAB506FE">>},
{<<"erlcass">>, <<"DCC19E6AEBBFFB5899D1F21071BC154411B05E422A4BA515D5CA08E88D786818">>},
{<<"antidote_pb_codec">>, <<"29891F77FB5DC8240495C425160EA152E9CA5753B7137E1866D9BA279F0F997B">>},
{<<"antidotec_pb">>, <<"70350652AE269BC561DA6DCC54DB6A1CFF203E01686E735C1341EFD925DEE598">>},
{<<"cowboy">>, <<"99AA50E94E685557CAD82E704457336A453D4ABCB77839AD22DBE71F311FCC06">>},
{<<"cowlib">>, <<"A7FFCD0917E6D50B4D5FB28E9E2085A0CEB3C97DEA310505F7460FF5ED764CE9">>},
{<<"eredis">>, <<"0B8E9CFC2C00FA1374CD107EA63B49BE08D933DF2CF175E6A89B73DD9C380DE4">>},
{<<"erlcass">>, <<"BE383601A8F29CE645B428BC25D0F5E9F490630811D4BD5C1DE8A7AD6C6AB04B">>},
{<<"goldrush">>, <<"F06E5D5F1277DA5C413E84D5A2924174182FB108DABB39D5EC548B27424CD106">>},
{<<"hamcrest">>, <<"FB7B2C92D252A1E9DB936750B86089ADDAEBEB8F87967FB4BBDDA61E8863338E">>},
{<<"jsx">>, <<"D2F6E5F069C00266CAD52FB15D87C428579EA4D7D73A33669E12679E203329DD">>},
{<<"lager">>, <<"23C8F5ABC4189F46804791E16BF6421C14EBC5B529DC113BC54639C6C62F255D">>},
{<<"poolboy">>, <<"6B46163901CFD0A1B43D692657ED9D7E599853B3B21B95AE5AE0A777CF9B6CA8">>},
{<<"ranch">>, <<"F04166F456790FEE2AC1AA05A02745CC75783C2BFB26D39FAF6AEFC9A3D3A58A">>},
{<<"jsx">>, <<"77760560D6AC2B8C51FD4C980E9E19B784016AA70BE354CE746472C33BEB0B1C">>},
{<<"lager">>, <<"563AB17CD32134A3DD17EC3B3622E6D8F827506AA4F8C489158879BED87D980B">>},
{<<"poolboy">>, <<"392B007A1693A64540CEAD79830443ABF5762F5D30CF50BC95CB2C1AAAFA006B">>},
{<<"ranch">>, <<"6B1FAB51B49196860B733A49C07604465A47BDB78AA10C1C16A3D199F7F8C881">>},
{<<"riak_client">>, <<"6B78373E576D80C7020BCBDA3B2C102221D32863580404F59D8791E5CDC19E79">>},
{<<"riak_pb">>, <<"48FFBF66DBB3F136AB9A7134BAC4E496754BAA5EF58C4F50A61326736D996390">>}]}
].
105 changes: 25 additions & 80 deletions src/fmke.erl
Original file line number Diff line number Diff line change
Expand Up @@ -81,65 +81,10 @@ handle_call(get_status, _From, Adapter) ->
] ++ EnvVals,
{reply, Reply, Adapter};

handle_call({create_patient, Id, Name, Address}, _From, Adapter) ->
{reply, Adapter:create_patient(Id, Name, Address), Adapter};

handle_call({create_pharmacy, Id, Name, Address}, _From, Adapter) ->
{reply, Adapter:create_pharmacy(Id, Name, Address), Adapter};

handle_call({create_facility, Id, Name, Address, Type}, _From, Adapter) ->
{reply, Adapter:create_facility(Id, Name, Address, Type), Adapter};

handle_call({create_staff, Id, Name, Address, Speciality}, _From, Adapter) ->
{reply, Adapter:create_staff(Id, Name, Address, Speciality), Adapter};

handle_call({create_prescription, Id, PatientId, PrescriberId, PharmacyId, DatePrescribed, Drugs}, _From, Adapter) ->
{reply, Adapter:create_prescription(Id, PatientId, PrescriberId, PharmacyId, DatePrescribed, Drugs), Adapter};

handle_call({get_facility_by_id, Id}, _From, Adapter) ->
{reply, Adapter:get_facility_by_id(Id), Adapter};

handle_call({get_patient_by_id, Id}, _From, Adapter) ->
{reply, Adapter:get_patient_by_id(Id), Adapter};

handle_call({get_pharmacy_by_id, Id}, _From, Adapter) ->
{reply, Adapter:get_pharmacy_by_id(Id), Adapter};

handle_call({get_pharmacy_prescriptions, Id}, _From, Adapter) ->
{reply, Adapter:get_pharmacy_prescriptions(Id), Adapter};

handle_call({get_processed_pharmacy_prescriptions, Id}, _From, Adapter) ->
{reply, Adapter:get_processed_pharmacy_prescriptions(Id), Adapter};

handle_call({get_prescription_by_id, Id}, _From, Adapter) ->
{reply, Adapter:get_prescription_by_id(Id), Adapter};

handle_call({get_prescription_medication, Id}, _From, Adapter) ->
{reply, Adapter:get_prescription_medication(Id), Adapter};

handle_call({get_staff_by_id, Id}, _From, Adapter) ->
{reply, Adapter:get_staff_by_id(Id), Adapter};

handle_call({get_staff_prescriptions, Id}, _From, Adapter) ->
{reply, Adapter:get_staff_prescriptions(Id), Adapter};

handle_call({update_patient_details, Id, Name, Address}, _From, Adapter) ->
{reply, Adapter:update_patient_details(Id, Name, Address), Adapter};

handle_call({update_pharmacy_details, Id, Name, Address}, _From, Adapter) ->
{reply, Adapter:update_pharmacy_details(Id, Name, Address), Adapter};

handle_call({update_facility_details, Id, Name, Address, Type}, _From, Adapter) ->
{reply, Adapter:update_facility_details(Id, Name, Address, Type), Adapter};

handle_call({update_staff_details, Id, Name, Address, Speciality}, _From, Adapter) ->
{reply, Adapter:update_staff_details(Id, Name, Address, Speciality), Adapter};

handle_call({update_prescription_medication, Id, Operation, Drugs}, _From, Adapter) ->
{reply, Adapter:update_prescription_medication(Id, Operation, Drugs), Adapter};

handle_call({process_prescription, Id, Date}, _From, Adapter) ->
{reply, Adapter:process_prescription(Id, Date), Adapter}.
handle_call(Op, From, State) ->
Worker = poolboy:checkout(handlers),
gen_server:cast(Worker, {Op, From}),
{noreply, State}.

%%-----------------------------------------------------------------------------
%% Create functions - no transactional context
Expand All @@ -150,29 +95,29 @@ handle_call({process_prescription, Id, Date}, _From, Adapter) ->
%% and if so the operation fails.
-spec create_patient(id(), string(), string()) -> ok | {error, reason()}.
create_patient(Id, Name, Address) ->
gen_server:call(?MODULE, {create_patient, Id, Name, Address}).
gen_server:call(?MODULE, {create, patient, [Id, Name, Address]}).

%% Adds a pharmacy to the FMK-- system if the ID for the pharmacy has not yet been seen.
-spec create_pharmacy(id(), string(), string()) -> ok | {error, reason()}.
create_pharmacy(Id, Name, Address) ->
gen_server:call(?MODULE, {create_pharmacy, Id, Name, Address}).
gen_server:call(?MODULE, {create, pharmacy, [Id, Name, Address]}).

%% Adds a facility to the FMK-- system if the ID for the facility has not yet been seen.
-spec create_facility(id(), string(), string(), string()) -> ok | {error, reason()}.
create_facility(Id, Name, Address, Type) ->
gen_server:call(?MODULE, {create_facility, Id, Name, Address, Type}).
gen_server:call(?MODULE, {create, facility, [Id, Name, Address, Type]}).

%% Adds a staff member to the FMK-- system if the ID for the member has not yet been seen.
-spec create_staff(id(), string(), string(), string()) -> ok | {error, reason()}.
create_staff(Id, Name, Address, Speciality) ->
gen_server:call(?MODULE, {create_staff, Id, Name, Address, Speciality}).
gen_server:call(?MODULE, {create, staff, [Id, Name, Address, Speciality]}).

%% Creates a prescription that is associated with a pacient, prescriber (medicall staff),
%% pharmacy. The prescription also includes the prescription date and the list of drugs that should be administered.
-spec create_prescription(id(), id(), id(), id(), string(), [crdt()]) -> ok | {error, reason()}.
create_prescription(PrescriptionId, PatientId, PrescriberId, PharmacyId, DatePrescribed, Drugs) ->
gen_server:call(?MODULE,
{create_prescription, PrescriptionId, PatientId, PrescriberId, PharmacyId, DatePrescribed, Drugs}
{create, prescription, [PrescriptionId, PatientId, PrescriberId, PharmacyId, DatePrescribed, Drugs]}
).

%%-----------------------------------------------------------------------------
Expand All @@ -182,46 +127,46 @@ create_prescription(PrescriptionId, PatientId, PrescriberId, PharmacyId, DatePre
%% Fetches a patient by ID.
-spec get_patient_by_id(id()) -> patient() | {error, reason()}.
get_patient_by_id(Id) ->
gen_server:call(?MODULE, {get_patient_by_id, Id}).
gen_server:call(?MODULE, {read, patient, Id}).

%% Fetches a facility by id.
-spec get_facility_by_id(id()) -> facility() | {error, reason()}.
get_facility_by_id(Id) ->
gen_server:call(?MODULE, {get_facility_by_id, Id}).
gen_server:call(?MODULE, {read, facility, Id}).

%% Fetches a pharmacy by ID.
-spec get_pharmacy_by_id(id()) -> pharmacy() | {error, reason()}.
get_pharmacy_by_id(Id) ->
gen_server:call(?MODULE, {get_pharmacy_by_id, Id}).
gen_server:call(?MODULE, {read, pharmacy, Id}).

%% Fetches a prescription by ID.
-spec get_prescription_by_id(id()) -> prescription() | {error, reason()}.
get_prescription_by_id(Id) ->
gen_server:call(?MODULE, {get_prescription_by_id, Id}).
gen_server:call(?MODULE, {read, prescription, Id}).

%% Fetches a list of prescriptions given a certain pharmacy ID.
-spec get_pharmacy_prescriptions(id()) -> list(prescription() | binary()) | {error, reason()}.
get_pharmacy_prescriptions(Id) ->
gen_server:call(?MODULE, {get_pharmacy_prescriptions, Id}).
gen_server:call(?MODULE, {read, pharmacy, Id, prescriptions}).

-spec get_processed_pharmacy_prescriptions(id()) -> list(prescription() | binary()) | {error, reason()}.
get_processed_pharmacy_prescriptions(Id) ->
gen_server:call(?MODULE, {get_processed_pharmacy_prescriptions, Id}).
gen_server:call(?MODULE, {read, pharmacy, Id, processed_prescriptions}).

%% Fetches prescription medication by ID.
-spec get_prescription_medication(id()) -> [binary()] | {error, reason()}.
get_prescription_medication(Id) ->
gen_server:call(?MODULE, {get_prescription_medication, Id}).
gen_server:call(?MODULE, {read, prescription, Id, [drugs]}).

%% Fetches a staff member by ID.
-spec get_staff_by_id(id()) -> staff() | {error, reason()}.
get_staff_by_id(Id) ->
gen_server:call(?MODULE, {get_staff_by_id, Id}).
gen_server:call(?MODULE, {read, staff, Id}).

%% Fetches a list of prescriptions given a certain staff member ID.
-spec get_staff_prescriptions(id()) -> list(prescription() | binary()) | {error, reason()}.
get_staff_prescriptions(Id) ->
gen_server:call(?MODULE, {get_staff_prescriptions, Id}).
gen_server:call(?MODULE, {read, staff, Id, prescriptions}).

%%-----------------------------------------------------------------------------
%% Update functions - no transactional context
Expand All @@ -230,29 +175,29 @@ get_staff_prescriptions(Id) ->
%% Updates the personal details of a patient with a certain ID.
-spec update_patient_details(id(), string(), string()) -> ok | {error, reason()}.
update_patient_details(Id, Name, Address) ->
gen_server:call(?MODULE, {update_patient_details, Id, Name, Address}).
gen_server:call(?MODULE, {update, patient, [Id, Name, Address]}).

%% Updates the details of a pharmacy with a certain ID.
-spec update_pharmacy_details(id(), string(), string()) -> ok | {error, reason()}.
update_pharmacy_details(Id, Name, Address) ->
gen_server:call(?MODULE, {update_pharmacy_details, Id, Name, Address}).
gen_server:call(?MODULE, {update, pharmacy, [Id, Name, Address]}).

%% Updates the details of a facility with a certain ID.
-spec update_facility_details(id(), string(), string(), string()) -> ok | {error, reason()}.
update_facility_details(Id, Name, Address, Type) ->
gen_server:call(?MODULE, {update_facility_details, Id, Name, Address, Type}).
gen_server:call(?MODULE, {update, facility, [Id, Name, Address, Type]}).

%% Updates the details of a staff member with a certain ID.
-spec update_staff_details(id(), string(), string(), string()) -> ok | {error, reason()}.
update_staff_details(Id, Name, Address, Speciality) ->
gen_server:call(?MODULE, {update_staff_details, Id, Name, Address, Speciality}).
gen_server:call(?MODULE, {update, staff, [Id, Name, Address, Speciality]}).

-spec update_prescription_medication(id(), atom(), [string()]) -> ok | {error, reason()}.
update_prescription_medication(Id, Operation, Drugs) ->
gen_server:call(?MODULE, {update_prescription_medication, Id, Operation, Drugs}).
update_prescription_medication(Id, _Operation, Drugs) ->
gen_server:call(?MODULE, {update, prescription, Id, {drugs, add, Drugs}}).

process_prescription(Id, Date) ->
gen_server:call(?MODULE, {process_prescription, Id, Date}).
gen_server:call(?MODULE, {update, prescription, Id, {date_processed, Date}}).

%%-----------------------------------------------------------------------------
%% Helper functions
Expand Down
Loading

0 comments on commit eed698c

Please sign in to comment.