<div dir="ltr">Hi all<div><br></div><div>I've noticed that there's a lot of confusion over how to write a useful worker. Here follow some guidelines that you should be *very* certain of yourself before breaking (and probably talk to me about anyway). If there's any uncertainty about these, I'm more than happy to expand.</div><div><div><div><div><br></div><div>  * If you really just want to run a dumb function on its own goroutine, use worker.NewSimpleWorker.</div><div><br></div><div>  * If you just want to do something every <period>, use worker.NewPeriodicWorker.</div><div><br></div><div>  * If you want to react to watcher events, you should probably use worker.NewNotifyWorker or worker.NewStringsWorker.</div></div></div><div><div><div><br></div><div>  * If your worker has any methods outside the Worker interface, DO NOT use any of the above callback-style workers. Those methods, that need to communicate with the main goroutine, *need* to know that goroutine's state, so that they don't just hang forever.</div><div><br></div><div>  * To restate the previous point: basically *never* do a naked channel send/receive. If you're building a structure that makes you think you need them, you're most likely building the wrong structure.</div></div><div><br></div></div><div>  * If you're writing a custom worker, and not using a tomb.Tomb, you are almost certainly doing it wrong. Read the blog post [0] or, hell, just read the code [1] -- it's less than 200 lines and it's about 50% comments.</div></div><div><br></div><div>  * If you're letting tomb.ErrDying leak out of your workers to any clients, you are definitely doing it wrong -- you risk stopping another worker with that same error, which will quite rightly panic (because that tomb is *not* yet dying).</div><div><br></div><div>  * If it's possible for your worker to call .tomb.Done() more than once, or less than once, you are *definitely* doing it very very wrong indeed.</div><div><br></div><div>  * If you're using .tomb.Dead(), you are very probably doing it wrong -- the only reason (that I'm aware of) to select on that .Dead() rather than on .Dying() is to leak inappropriate information to your clients. They don't care if you're dying or dead; they care only that the component is no longer functioning reliably and cannot fulfil their requests. Full stop. Whatever started the component needs to know why it failed, but that parent is usually not the same entity as the client that's calling methods.</div><div><br></div><div>  * If you're using worker/singular, you are quite likely to be doing it wrong, because you've written a worker that breaks when distributed. Things like provisioner and firewaller only work that way because we weren't smart enough to write them better; but you should generally be writing workers that collaborate correctly with themselves, and eschewing the temptation to depend on the funky layer-breaking of singular.</div><div><div><div><br></div><div>  * If you're passing a *state.State into your worker, you are almost certainly doing it wrong. The layers go worker->apiserver->state, and any attempt to skip past the apiserver layer should be viewed with *extreme* suspicion.</div></div></div><div><br></div><div>  * Don't try to make a worker into a singleton (this isn't particularly related to workers, really, singleton is enough of an antipattern on its own [2] [3] [4]). Singletons are basically the same as global variables, except even worse, and if you try to make them responsible for goroutines they become more horrible still.</div><div><br></div><div>Did I miss anything major? Probably. If so, please remind me.</div><div><br></div><div>Cheers</div><div>William</div><div><br></div><div><br></div><div>[0] <a href="http://blog.labix.org/2011/10/09/death-of-goroutines-under-control">http://blog.labix.org/2011/10/09/death-of-goroutines-under-control</a></div><div>[1] <a href="http://launchpad.net/tomb">launchpad.net/tomb</a> (apparently... we really ought to be using v2, though) </div><div>[2] <a href="https://sites.google.com/site/steveyegge2/singleton-considered-stupid">https://sites.google.com/site/steveyegge2/singleton-considered-stupid</a> </div><div>[3] <a href="http://jalf.dk/blog/2010/03/singletons-solving-problems-you-didnt-know-you-never-had-since-1995/">http://jalf.dk/blog/2010/03/singletons-solving-problems-you-didnt-know-you-never-had-since-1995/</a></div><div>[4] <a href="http://programmers.stackexchange.com/questions/40373/so-singletons-are-bad-then-what/">http://programmers.stackexchange.com/questions/40373/so-singletons-are-bad-then-what/</a></div></div>