On Tue, 2015-03-31 at 11:26 -0400, Rafael Schloming wrote: > On Tue, Mar 31, 2015 at 11:02 AM, Alan Conway <[email protected]> wrote: > > > On Mon, 2015-03-30 at 00:11 +0100, Adrian Preston wrote: > > > Hello all, > > > > > > I've been following the development of the reactor API and think that it > > looks really neat. Is anyone working on a pure Java version? I'd be > > interested in helping. > > > > > > Regards > > > - Adrian > > > Unless stated otherwise above: > > > IBM United Kingdom Limited - Registered in England and Wales with number > > 741598. > > > Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire PO6 > > 3AU > > > > > > > I'm currently working on a Go version which is not directly relevant, > > but porting directly from the python handlers.py and it is pretty > > straightforward. That's where I would start. For Go I also had to wrap a > > bunch of lower-level proton details but the task should be easier for > > Java since all that stuff already exists in Java. > > > > In Go I am not using the proton reactor to establish or select over > > connections, so I'm not using any of the reactor or selectable events. I > > have a goroutine per connection pumping a proton transport with separate > > event handling per-connection so we have connection concurrency but each > > proton engine is only used in a single thread. > > > > This sounds to me like it is based on a bit of a missunderstanding of how > the reactor works. The reactor doesn't actually establish or select over > connections in C/Python. It is actually just mediating the request for > connection creation between whatever piece of application code wants a new > connection, and whatever handler has been configured to deal with I/O > related events. This allows for a significant amount of flexiblity since > you can have multiple I/O implementations without having to hard code your > app to work against a specific one. This is just as important a requirement > in Go or Java or any other language.
Yep I think I've misstated the issue for Go and I agree with you on Java. The real reason I'm not using the reactor is because event-loop programming is counter to the whole design of Go. I want to minimize it to handling AMQP-related events. The proton engine API (pn_transport, pn_connnection et. al) already gives me an IO-neutral bytes in/bytes out interface. I run a goroutine per connection to pump a pn_transport and handle AMQP-related events. Go provides standard connection handling and IO abstractions that are more suited to Go than a mirror of the reactor API. I am doing an event-based API for AMQP events: it is a straight wrap of the proton C API + port of python MessageHandler API. I originally hoped to skip that wrapping and use the proton C API directly to implement a concurrent Go API (it is laughably easy to call C direct from Go.) However I decided to do the event wrapping for reasons: 1. I'm still thrashing on how the Go API should look I needed to make proton programming easy and fast while I experiment. C is never easy or fast ;) 2. Having an event layer that is a straight analog of the C/python reactive APIs will be valuable for cross-language development. 3. The first Go API I come up with will very likely need a lot of improving, again we want that to be easy and fast. So I will (shortly I hope) unveil the event based API, running an event loop per connection in its own goroutine (actually there are 3 goroutines per connection - one reading, one writing and one processing proton events) I've done initial experiments that prove we can use channels to inject behavior into the event-loop goroutine from other goroutines, and extract results. There might actually be channels carrying messages and acknowledgements, but more likely they will be carrying co-ordination information, and say a Link object may be composed of several channels plus non-channel storage. I'm not there yet. > > > I'm not sure what the right approach is for Java. Having a C-based > > reactor is useful in C and for some bindings (e.g. the python binding > > uses it) but in languages that have their own version of event > > loops/polling/selecting it may be better to go with the native > > approach. > > > > The reactor is pure code/data structure. I believe the correct approach for > Java would be a straightforward port, As long as it's possible to service connections concurrently I agree for Java (not having looked closely.) Java it is in the same concurrency category (heavy threads) as all our other binding languages (python, ruby, C++) so the reactor is probably appropriate. > and the correct approach for Go would > be a simple binding, just like all the other pure code/data pieces > (connection, transport, etc). Tthinking of the reactor as part of the I/O > subsystem is to misunderstand how it works. The reactor proper has been > carefully designed to not directly incorporate any I/O dependencies at all. > > In other words, don't think of the reactor as analogous to or a replacement > for the old Driver, think of the reactor as a (potentially) > multi-connection engine, or in UML terms: > > Reactor <>---> Connection <>--> Session <>---> Link <>---> Delivery > > Please excuse the ascii art UML. The diamonds are supposed to imply > containment by composition. That's why its a poor fit for Go. Handling multiple connections is much easier in Go than in C (or other non-concurrent language) and the natural concurrent way to do it does not fit under an event-loop interface.
