|
45 | 45 | start_link/1, |
46 | 46 | start_link/2, |
47 | 47 | stop/1, |
| 48 | + one_shot_query/4, |
48 | 49 | get_buffer_strategy_module/1, |
49 | 50 | with_connection/4, |
50 | 51 | with_connection/5 |
@@ -86,6 +87,94 @@ start_link(Config, restart) -> |
86 | 87 | Max_Retries = elysium_config:checkout_max_retry (Config), |
87 | 88 | start_channel(Config, Lb_Queue_Name, Max_Retries, -1, []). |
88 | 89 |
|
| 90 | +-spec stop(connection_id()) -> ok. |
| 91 | +%% @doc Stop an existing seestar_session. |
| 92 | +stop(Connection_Id) |
| 93 | + when is_pid(Connection_Id) -> |
| 94 | + seestar_session:stop(Connection_Id). |
| 95 | + |
| 96 | +-spec one_shot_query(config_type(), cassandra_node(), Query::string(), ssestar:consistency()) |
| 97 | + -> {ok, seestar_result:result()} | {error, seestar_error:error()}. |
| 98 | +%% @doc Connect, execute raw CQL and close a connection to Cassandra. |
| 99 | +one_shot_query(Config, {Host, Port} = _Node, Query, Consistency) |
| 100 | + when is_list(Host), is_integer(Port), Port > 0 -> |
| 101 | + case get_one_shot_connection(Config, Host, Port) of |
| 102 | + {ok, Connection_Id} -> |
| 103 | + try seestar_session:perform(Connection_Id, Query, Consistency) |
| 104 | + after stop(Connection_Id) |
| 105 | + end |
| 106 | + end. |
| 107 | + |
| 108 | +-spec get_buffer_strategy_module(config_type()) -> {buffering(), buffering_strategy_module()}. |
| 109 | +%% @doc Get the module corresponding to the configured buffering strategy. |
| 110 | +get_buffer_strategy_module(Config) -> |
| 111 | + true = elysium_config:is_valid_config(Config), |
| 112 | + Buffering_Strategy = elysium_config:connection_buffering_strategy(Config), |
| 113 | + BS_Module = case Buffering_Strategy of |
| 114 | + none -> elysium_nobs; |
| 115 | + parallel -> elysium_bs_parallel; |
| 116 | + serial -> elysium_bs_serial |
| 117 | + end, |
| 118 | + {Buffering_Strategy, BS_Module}. |
| 119 | + |
| 120 | +-spec with_connection(config_type(), fun((pid(), Args, Consist) -> Result), Args, Consistency) |
| 121 | + -> {error, no_db_connections} |
| 122 | + | Result when Args :: [any()], |
| 123 | + Consist :: seestar:consistency(), |
| 124 | + Consistency :: seestar:consistency(), |
| 125 | + Result :: any(). |
| 126 | +%% @doc |
| 127 | +%% Obtain an active seestar_session and use it solely |
| 128 | +%% for the duration required to execute a fun which |
| 129 | +%% requires access to Cassandra. |
| 130 | +%% @end |
| 131 | +with_connection(Config, Session_Fun, Args, Consistency) |
| 132 | + when is_function(Session_Fun, 3), is_list(Args) -> |
| 133 | + {Buffering_Strategy, BS_Module} = get_buffer_strategy_module(Config), |
| 134 | + case elysium_buffering_strategy:checkout_connection(Config, BS_Module) of |
| 135 | + none_available -> |
| 136 | + buffer_bare_fun_call(Config, Session_Fun, Args, Consistency, Buffering_Strategy); |
| 137 | + {Node, Sid} when is_pid(Sid) -> |
| 138 | + case is_process_alive(Sid) of |
| 139 | + false -> with_connection(Config, Session_Fun, Args, Consistency); |
| 140 | + true -> Reply_Timeout = elysium_config:request_reply_timeout(Config), |
| 141 | + Query_Request = {bare_fun, Config, Session_Fun, Args, Consistency}, |
| 142 | + Reply = elysium_buffering_strategy:handle_pending_request |
| 143 | + (Config, BS_Module, 0, Reply_Timeout, Node, Sid, Query_Request), |
| 144 | + handle_bare_fun_reply(Buffering_Strategy, Reply, ?MODULE, with_connection, Args) |
| 145 | + end |
| 146 | + end. |
| 147 | + |
| 148 | +-spec with_connection(config_type(), module(), Fun::atom(), Args::[any()], seestar:consistency()) |
| 149 | + -> {error, no_db_connections} | any(). |
| 150 | +%% @doc |
| 151 | +%% Obtain an active seestar_session and use it solely |
| 152 | +%% for the duration required to execute Mod:Fun |
| 153 | +%% which requires access to Cassandra. |
| 154 | +%% @end |
| 155 | +with_connection(Config, Mod, Fun, Args, Consistency) |
| 156 | + when is_atom(Mod), is_atom(Fun), is_list(Args) -> |
| 157 | + true = erlang:function_exported(Mod, Fun, 3), |
| 158 | + {Buffering_Strategy, BS_Module} = get_buffer_strategy_module(Config), |
| 159 | + case elysium_buffering_strategy:checkout_connection(Config, BS_Module) of |
| 160 | + none_available -> |
| 161 | + buffer_mod_fun_call(Config, Mod, Fun, Args, Consistency, Buffering_Strategy); |
| 162 | + {Node, Sid} when is_pid(Sid) -> |
| 163 | + case is_process_alive(Sid) of |
| 164 | + false -> with_connection(Config, Mod, Fun, Args, Consistency); |
| 165 | + true -> Reply_Timeout = elysium_config:request_reply_timeout(Config), |
| 166 | + Query_Request = {mod_fun, Config, Mod, Fun, Args, Consistency}, |
| 167 | + Reply = elysium_buffering_strategy:handle_pending_request |
| 168 | + (Config, BS_Module, 0, Reply_Timeout, Node, Sid, Query_Request), |
| 169 | + handle_mod_fun_reply(Buffering_Strategy, Reply, Mod, Fun, Args) |
| 170 | + end |
| 171 | + end. |
| 172 | + |
| 173 | + |
| 174 | +%%%----------------------------------------------------------------------- |
| 175 | +%%% Internal connection support functions |
| 176 | +%%%----------------------------------------------------------------------- |
| 177 | + |
89 | 178 | start_channel(_Config, _Lb_Queue_Name, Max_Retries, Times_Tried, Attempted_Connections) |
90 | 179 | when Times_Tried >= Max_Retries -> |
91 | 180 | {error, {cassandra_not_available, Attempted_Connections}}; |
@@ -130,61 +219,32 @@ try_connect(Config, Lb_Queue_Name, Max_Retries, Times_Tried, Attempted_Connectio |
130 | 219 | start_channel(Config, Lb_Queue_Name, Max_Retries, Times_Tried+1, |
131 | 220 | [Node_Failure | Attempted_Connections]) |
132 | 221 |
|
133 | | - catch Error:Class -> |
134 | | - Node_Failure = {Node, {Error, Class}}, |
| 222 | + catch Err:Class -> |
| 223 | + Node_Failure = {Node, {Err, Class}}, |
135 | 224 | start_channel(Config, Lb_Queue_Name, Max_Retries, Times_Tried+1, |
136 | 225 | [Node_Failure | Attempted_Connections]) |
137 | 226 |
|
138 | 227 | %% Ensure that we get the Node checked back in. |
139 | 228 | after _ = ets_buffer:write_dedicated(Lb_Queue_Name, Node) |
140 | 229 | end. |
141 | 230 |
|
142 | | --spec stop(pid()) -> ok. |
143 | | -%% @doc Stop an existing seestar_session. |
144 | | -stop(Session_Id) |
145 | | - when is_pid(Session_Id) -> |
146 | | - seestar_session:stop(Session_Id). |
147 | | - |
148 | | --spec get_buffer_strategy_module(config_type()) -> {buffering(), module()}. |
149 | | -%% @doc Get the module corresponding to the configured buffering strategy. |
150 | | -get_buffer_strategy_module(Config) -> |
151 | | - true = elysium_config:is_valid_config(Config), |
152 | | - Buffering_Strategy = elysium_config:connection_buffering_strategy(Config), |
153 | | - BS_Module = case Buffering_Strategy of |
154 | | - none -> elysium_nobs; |
155 | | - parallel -> elysium_bs_parallel; |
156 | | - serial -> elysium_bs_serial |
157 | | - end, |
158 | | - {Buffering_Strategy, BS_Module}. |
| 231 | +-spec get_one_shot_connection(config_type(), string(), pos_integer()) -> {ok, connection_id()} | any(). |
| 232 | +get_one_shot_connection(Config, Host, Port) -> |
| 233 | + Connect_Timeout = elysium_config:connect_timeout (Config), |
| 234 | + try seestar_session:start_link(Host, Port, |
| 235 | + [ |
| 236 | + %% {send_timeout, Send_Timeout} |
| 237 | + ], |
| 238 | + [{connect_timeout, Connect_Timeout}]) of |
| 239 | + {ok, Connection_Id} = Connection when is_pid(Connection_Id) -> Connection; |
| 240 | + Error -> Error |
| 241 | + catch Err:Class -> {Err, Class} |
| 242 | + end. |
159 | 243 |
|
160 | 244 |
|
161 | | --spec with_connection(config_type(), fun((pid(), Args, Consist) -> Result), Args, Consistency) |
162 | | - -> {error, no_db_connections} |
163 | | - | Result when Args :: [any()], |
164 | | - Consist :: seestar:consistency(), |
165 | | - Consistency :: seestar:consistency(), |
166 | | - Result :: any(). |
167 | | -%% @doc |
168 | | -%% Obtain an active seestar_session and use it solely |
169 | | -%% for the duration required to execute a fun which |
170 | | -%% requires access to Cassandra. |
171 | | -%% @end |
172 | | -with_connection(Config, Session_Fun, Args, Consistency) |
173 | | - when is_function(Session_Fun, 3), is_list(Args) -> |
174 | | - {Buffering_Strategy, BS_Module} = get_buffer_strategy_module(Config), |
175 | | - case elysium_buffering_strategy:checkout_connection(Config, BS_Module) of |
176 | | - none_available -> |
177 | | - buffer_bare_fun_call(Config, Session_Fun, Args, Consistency, Buffering_Strategy); |
178 | | - {Node, Sid} when is_pid(Sid) -> |
179 | | - case is_process_alive(Sid) of |
180 | | - false -> with_connection(Config, Session_Fun, Args, Consistency); |
181 | | - true -> Reply_Timeout = elysium_config:request_reply_timeout(Config), |
182 | | - Query_Request = {bare_fun, Config, Session_Fun, Args, Consistency}, |
183 | | - Reply = elysium_buffering_strategy:handle_pending_request |
184 | | - (Config, BS_Module, 0, Reply_Timeout, Node, Sid, Query_Request), |
185 | | - handle_bare_fun_reply(Buffering_Strategy, Reply, ?MODULE, with_connection, Args) |
186 | | - end |
187 | | - end. |
| 245 | +%%%----------------------------------------------------------------------- |
| 246 | +%%% Internal with_connection support functions |
| 247 | +%%%----------------------------------------------------------------------- |
188 | 248 |
|
189 | 249 | buffer_bare_fun_call(_Config, _Session_Fun, _Args, _Consistency, none) -> {error, no_db_connections}; |
190 | 250 | buffer_bare_fun_call( Config, Session_Fun, Args, Consistency, Type) -> |
@@ -212,32 +272,6 @@ handle_bare_fun_reply(serial, {Err_Type, _Err_Data} = Error, Mod, Fun, Args) |
212 | 272 | handle_bare_fun_reply(_Buffering_Strategy, Reply, _Mod, _Fun, _Args) -> |
213 | 273 | Reply. |
214 | 274 |
|
215 | | - |
216 | | --spec with_connection(config_type(), module(), Fun::atom(), Args::[any()], seestar:consistency()) |
217 | | - -> {error, no_db_connections} | any(). |
218 | | -%% @doc |
219 | | -%% Obtain an active seestar_session and use it solely |
220 | | -%% for the duration required to execute Mod:Fun |
221 | | -%% which requires access to Cassandra. |
222 | | -%% @end |
223 | | -with_connection(Config, Mod, Fun, Args, Consistency) |
224 | | - when is_atom(Mod), is_atom(Fun), is_list(Args) -> |
225 | | - true = erlang:function_exported(Mod, Fun, 3), |
226 | | - {Buffering_Strategy, BS_Module} = get_buffer_strategy_module(Config), |
227 | | - case elysium_buffering_strategy:checkout_connection(Config, BS_Module) of |
228 | | - none_available -> |
229 | | - buffer_mod_fun_call(Config, Mod, Fun, Args, Consistency, Buffering_Strategy); |
230 | | - {Node, Sid} when is_pid(Sid) -> |
231 | | - case is_process_alive(Sid) of |
232 | | - false -> with_connection(Config, Mod, Fun, Args, Consistency); |
233 | | - true -> Reply_Timeout = elysium_config:request_reply_timeout(Config), |
234 | | - Query_Request = {mod_fun, Config, Mod, Fun, Args, Consistency}, |
235 | | - Reply = elysium_buffering_strategy:handle_pending_request |
236 | | - (Config, BS_Module, 0, Reply_Timeout, Node, Sid, Query_Request), |
237 | | - handle_mod_fun_reply(Buffering_Strategy, Reply, Mod, Fun, Args) |
238 | | - end |
239 | | - end. |
240 | | - |
241 | 275 | buffer_mod_fun_call(_Config, _Mod, _Fun, _Args, _Consistency, none) -> {error, no_db_connections}; |
242 | 276 | buffer_mod_fun_call( Config, Mod, Fun, Args, Consistency, parallel) -> |
243 | 277 | Reply = elysium_buffering_strategy:pend_request(Config, {mod_fun, Config, Mod, Fun, Args, Consistency}), |
|
0 commit comments