I’m in the process of building an availability monitor. I enqueue a request/response using a worker, which then performs code found in my models. This generally means performing the actual request, checking matches on certain values of the response (status code, body, headers), and potentially sending an alert based on a policy.
I’m only half a week into designing it, and have already started to abuse those beautiful pipes, and wondering how best to approach this.
Here is a very simplified flow. Below, the request_response
is my model struct, whereas the poison
is a HTTPoison struct. I’ve just wrote this out from scratch and the naming is not the same in my codebas – this is just for brevity.
defmodule Check do
def enqueue_check(check_id) do
MyWorker.enqueue(check_id)
end
def perform(check) do
RequestResponse.new_from_check(check)
|> RequestResponse.perform
end
end
defmodule MyWorker do
def perform(check_id) do
# find check and run Check.perform
end
end
defmodule RequestResponse do
def perform(request_response) do
make_request(request_response) |> process_response
end
def make_request(request_response) do
# HTTPoison request, returns {:ok/error, response}
{request_response, poison}
end
def process_response({request_response, poison}) do
{request_response, poison} = request_response
|> run_checks
|> run_alerts
Repo.insert!(request_response)
end
def run_checks({request_response, poison}) do
request_response
|> check_status_match
|> check_etc
|> check_etc
|> check_etc
|> pass_or_fail
end
end
I’m wondering if this reliance on piping is a good idea or is going to lead to trouble in the future? Piped functions leading to other piped functions? To be fair, I find it simple enough to follow, but I did build it
I should also note, this is mostly in my models, but I do plan to encapsulate these different responsibilities in separate modules.
One of the big issues I’ve had is that some of the functions I’m piping might only require a single argument (the request_response), and some require a couple (a HTTPoison struct). But because of my perhaps abuse of pipes, I’m having to pass and return both of these arguments in each function.
Another point I would like advice on is the process_response
function. I am retrieving the modified request_response
after piping it through my run_checks
, and then inserting it using a repo. Does this seem sane? Any glaring holes that might be worth considering? I’ve not even added error messaging, so want to be sure I’m starting on the right foot.
Would appreciate any input.