This might be a stupid question, but I don’t see it anywhere. My question is on the maintainability on deployment.
One service I have is a slack bot running in contanier (a simple module called SlackPost
uses GenServer). The idea is that all other services talks to the bot to post to a slack channel. Currently I set RELEASE_NODE=slackbot@localhost and RELEASE_COOKIE=… before the app runs (app is built using mix release).
Now I am implementing another service B that runs in another container, which talks to slackbot@localhost, so I write this helper function in B:
def log(message) do
GenServer.call({SlackPost, :slackbot@localhost}, {:service_logs, message})
end
The part I am worried is the plain, hardcoded module name SlackPost
, and node name :slackbot@localhost
:
- The atom
SlackPost
comes from nowhere in the project B, not even in the dependency list. A refactoring of the module name in source will break thelog
function. - The sname
:slackbot@localhost
belongs to configuration but got hardcoded at call site. Changes in the RELEASE_NODE of slackbot breaks my code.
What’s the idiomatic way to talk to a remote node in a maintainable way? At least I want to have a source of truth for the node name part; changing slackbot@localhost
to SlackbotAlice@localhost
needs to change only one place for deployment and requires no changes at all for other services.
One way I can think of is to write helper functions in SlackPost, and import SlackPost in other services, instead of calling GenServer.call(...)
, call SlackPost.service_logs_remote(...)
.
defmodule SlackPost do
def service_logs(message) do
GenServer.call(__MODULE__, {:service_logs, message})
end
def service_logs_remote(message) do
GenServer.call({__MODULE__, get_sname()}, {:service_logs, message})
end
end
Thanks!