-
Notifications
You must be signed in to change notification settings - Fork 61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Managing system restarts from within the components #20
Comments
The above use case is not limited to the components restarting themselves. For example, a watchdog component that checks the system health should be able to restart parts of the system as needed. Thus, such components must be able to access the system var somehow. How would you go about implementing this? |
There are two broad solutions to this. One solution is that the component itself can take care of restarting connections. A common example of this is a SQL connection pool. If a connection is broken, the pool will give the user a new connection. All I/O connections should be wrapped in boundaries anyway, both to allow easier testing and to loosen the coupling between the connection and the rest of your code. Another solution is to introduce a watchdog component and pass in the components you want to watch as references. For example: {:example/server {:port 8080}
:example/watchdog #{#ig/ref :example/server}} Perhaps the server adheres to a protocol that allows it to be restarted. Alternatively, and usually preferably, this can be done at a system level. If something goes wrong and we lose a connection or the server goes down, we can just log the problem then exit the application with a failure code. If we're using something like systemd to manage our application, it will be restarted automatically. |
I guess this is what I was missing. I was exposing too much of the component to its children. Are there reasonably complete examples of systems built on |
But in order for this to work I need to design the |
Ah, sorry, I should have explained further. Boundaries are a Duct concept, and as I've been writing a lot of Duct recently, and the new Duct alpha makes heavy use of Integrant, I forgot I was replying to an issue on the Integrant repository, and not the Duct repository. So let me start again 😃 . I've found it good practice to avoid tightly coupling my functional code with the code that handles I/O. Some languages, like Haskell, enforce this distinction; in Clojure we have to have a little more self-discipline. A websocket is a little complex for an example, because we need to handle channel closing, errors, and so forth. Instead, consider a SQL connection pool, which already does all those things for us. We could interact directly with the connection: (defn get-user [spec email]
(jdbc/query spec ["SELECT * FROM users WHERE email = ?" email]))
(defmethod ig/init-key :database/sql [_ options]
{:datasource (db/connect-pool options)}) But I've found it's useful to add a layer inbetween to loosen the coupling: (defprotocol Users
(get-user [db email]))
(defrecord DatabaseBoundary [spec]
Users
(get-user [_ email]
(jdbc/query spec ["SELECT * FROM users WHERE email = ?" email])))
(defmethod ig/init-key :database/sql [_ options]
(->DatabaseBoundary {:datasource (db/connect-pool options)})) In this example, the |
The However, now that I've thought about it a little further, I don't think I'd recommend a For connections and so forth, we can give the component itself a connection pool, or some way of restarting the connection when it's dropped. This is a common problem, so there may be libraries out there to simplify this. |
Yes. I read your note on boundaries here and will try to follow the advice from now on.
I have multiple websockets open (listening for transactions) and restarting the full application on every websocket disconnect is really not an option.
I am using Thank you for all the input! |
Hi,
What is the idiomatic way to manage faults and restarts from within the system? Let's say I have a web socket and a couple of components that depend on that socket:
When web socket
:feed/ws
breaks for external reasons I would like to automatically restart it and all its dependencies. Thanks.The text was updated successfully, but these errors were encountered: