qpid-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Alan Conway <acon...@redhat.com>
Subject Re: Azure Service Bus receiver timing out with electron go binding
Date Thu, 06 Oct 2016 15:12:14 GMT
On Wed, 2016-10-05 at 04:46 -0700, Tobias Duckworth wrote:
> Thanks Robbie,
> 
> Didn't realise I am on the wrong list, sorry about that.
> 
> OK, so comparing what I see in a non connection_engine build to a
> connection_engine one.
> 
> From the Wireshark traces of both I can see that in the
> connection_engine
> build the Azure end is sending empty (presumably heartbeat) frames
> every 70
> seconds, but the qpid-proton end is never sending any (although it
> does
> respond to the Azure ones).
> 
> On the non connection_engine build both ends are sending periodic
> empty
> frames - The qpid-proton ones are every 120 seconds, which is half
> the
> idle_timeout specified in the connect packets coming from Azure.
> 
> So it looks like I need to convince the connection_engine to send out
> heartbeat frames and it will be fixed.

Correct. I just fixed this in the Go binding, you need to call
pn_transport_tick(pn_connnection_engine_transport(eng)) periodically
and it will take care of heartbeats for you.

I am working on a C "driver" framework with a C example (using the
libuv library) to show everything that needs to be done in a complete
proton driver.  

Meanwhile the Go code is model you can translate to C. Basically you
need to call pn_transport_tick when there is a PN_TRANSPORT event
(starts the first tick, and many anounce changes to the tick schedule)
and also ticks chain - each call to tick returns a time to call it
again.

Here's an annotated explanation, notes with XX: 

// Let proton run timed activity and set up the next tick
func (eng *Engine) tick() {
	now := time.Now() // XX Gets current time.
        // XX pn_timestamp_t next = pn_transport_tick(pn_connection_engine_transport(eng));
	next := eng.Transport().Tick(now)
        // XX if (next != 0) {
	if !next.IsZero() {
                // Set some timer mechanism to fire at time `next`,
                // In Go we subtract now from next to get a relative time.
		eng.timer.Reset(next.Sub(now))
	}
}

func (eng *Engine) dispatch() bool {
	var needTick bool // Set if we need to tick the transport.
	for {
		cevent := C.pn_connection_engine_dispatch(&eng.engine)
		if cevent == nil {
			break
		}
		event := makeEvent(cevent, eng)
		if event.Type() == ETransport {
			needTick = true
		}
		for _, h := range eng.handlers {
			h.HandleEvent(event)
		}
	}
	if needTick {
		eng.tick()
	}
	return !bool(C.pn_connection_engine_finished(&eng.engine))
}

The Go IO loop monitors the timer as well as read/write IO and calls
dispatch() if it fires.

Should be easy to translate into C, but you will need to add some
scheduled wakeup to your poller or whatever you are using for IO.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@qpid.apache.org
For additional commands, e-mail: users-help@qpid.apache.org


Mime
View raw message