Suture – Supervisor Trees for Go
jerf.org
jerf.org
Second, I have found a lot of utility comes from having a standardized "this is my set of services" object that can be manipulated. A lot of my Go programs have converged on "a lot of libraries providing a lot of services, and a rather grotty-looking ~100-200 line 'main.go' that does all the nasty ops-type work of propagating configuration to them and plumbing them all together". Most of those main.go's have a supervisor created near the top, various bits of library functionality added to the supervisor as the file goes along, and the last line is supervisor.Serve().
In terms of error handling, while I have seen it keep production services up in a reasonable manner, Go code tends not to crash much, if you mind your errors properly. The orchestration may actually be the nicer thing. I've gotten a few issues in the github project and refined things a bit over the past year; one of the use cases that came up is that shutting down the services with one ".Stop()" call has been useful to people.
(We also got an interesting example of when penetrating an abstraction can come in handy; supervisors take a couple of functions to allow you to log some things. When a supervisor child is added to a supervisor parent, the log functions are copied from parent to child by penetrating the Service with a type assertion. This makes it easier to compose supervisors because the child supervisors no longer have to guess at what logging you want.)
All in all, while I will re-emphasize strongly that it is not a straight-up replacement for all bits of Erlang functionality as I explain at some length in the post, I have found it useful enough to be worth writing and using myself. Whether it passes the bar for "worth importing as a dependency", well, that's your call.
(Also, I'm guessing this came up again for the explanation of why imperative languages generally don't have thread-killing capabilities?)
This is really cool BTW, great work! I was following it more when it was first announced but unfortunately I haven't been using Go for work these days :| Would be fun though to take some old stuff and rejig it with Suture. You're right though, the Go code doesn't crash much.
If an Erlang process crashes when processing a message, and it is restarted, is the message replayed automatically by the runtime, or provide some kind of mechanism to recover the message as well?
You can also do things like send a message across a node boundary to a node no longer connected, which looks a lot like sending a message to a process that crashes it. In the general case, you don't get an "error" message when that happens or anything, you just get timeouts as if the remote node received it but never acknowledged it. It's "just another failure", just another day at the office, nothing unusual here.
I suppose this would still have issues dealing with unfinished work under a mutex.
Are there any more examples available? Folk using it in production?
This is how asynchronous processes might look like:
func procA (cb func(error)) (func(error)){
var enter, something, leave func(error)
var shared int
enter = func (error err){
...
shared ++
...
waitForSomething (something)
}
something = func (error err){
if err != nil {
post (leave)
return
}
...
}
...
leave = func (error err){
...
post (cb)
}
return enter
}
It is also easy to preserve same guaranties and schedule such processes to multiple cores. Although to do that in Go you would need to explicitly pass a struct with all of the information about each process, its resources and its environments.