- I don't understand why you'd want more than one type of
HandlerperReader, so why not addHandlertoReader's constructor with an optional concurrencyintonReader? - A
HandlerFuncfunction type would be a nice alternative interface for stateless handlers or closures. - Graceful shutdown is confusing and awkward. A (non-blocking) 30 second sleep in
Stopmust be followed by blocking on theExitChan(which should be astruct{})? Why not simply makeStopblock until handlers have exited gracefully? Reader.Configureis awkward, but makes sense if you want to provide validation forReaderfields. However, it seems strange to make the fields public and provide a setter with no indication which is the proper mechanism to use.- Perhaps a separate
ReaderConfigtype (liketls.Config) which could be built as a struct literal and passed toReader.Configure(or a constructor?) would allow for validation and public fields. - Proper
Readerinitialization is non-obvious. I think the order is:
r := NewReader()r.AddHandler(h)r.ConnectToLookupd(...)<-r.ExitChan # probably select on signals here as well
-
ReaderandWriterare confusing names since they don't implement the expected interfaces.ConsumerandPublishermight be more clear (and could be in separate packages since they're almost always used independently). -
I expected the
AddHandlerinterface to allow me to subscribe to multiple nsq channels within a single reader. Managing separateReaders makes getting graceful shutdown right even trickier. -
Use of Go's builtin
logpackage is frustrating (very noisy during integration tests) but understandable. Not sure if there's a better answer here. -
DecodeMessageshould use the more efficientByteOrdermethods: http://golang.org/pkg/encoding/binary/#ByteOrder -
Unnecessary slice: https://github.com/bitly/go-nsq/blob/master/message.go#L83- It is necessary, Id is a byte array.
GET /empty_channelreturns a 500 on unknown topics, should be a 400 or 404.