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.



Reply via email to