crossbario / crossbar

Crossbar.io - WAMP application router
https://crossbar.io/
Other
2.05k stars 274 forks source link

Order of subscribed message and subscription meta events #369

Open NomAnor opened 9 years ago

NomAnor commented 9 years ago

I'm using the crossbar 'wamp.subscription.on_create' meta event mechanism to monitor subscriptions to URIs under a specific prefix. I use a third party library to monitor certain events and publish these on the URIs. The problem is, that when my 'on_create' callback creates the third party monitor, the change callback from that library can get called and then my ApplicationSession calls publish before the 'on_create' callback is finished. The crossbar broker publishes to the 'on_create' URI before it sends the SUBSCRIBED message resulting in an exception because an EVENT message is received before the SUBSCRIBED message. I think the meta events should only be published to when the subscriptions are complete, e.g. the SUBSCRIBED message has been send.

--- Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/22823382-order-of-subscribed-message-and-subscription-meta-events?utm_campaign=plugin&utm_content=tracker%2F462544&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F462544&utm_medium=issues&utm_source=github).
goeddea commented 9 years ago

I don't fully understand the scenario:

Where does the exception occur then?

NomAnor commented 9 years ago
  1. Crossbar receveives a subscription request from a client
  2. it fires 'wamp.subscription.on_create'
  3. In the handler for on_create my code creates a third party monitor with a callback function
  4. The third party libraries calls the callback function (I have no control when this happens)
  5. The callback function publishes some data trough crossbar, crossbar sends an EVENT message
  6. The on_create handler returns and crossbar sends the SUBSCRIBED message
  7. The client (javascript) receives the EVENT message before the SUBSCRIBED message and closes the connection. The error is logged in the javascript console.

The problem occurs when you try to publish an event in the on_create handler (to the same uri which generated the on_create event), because the EVENT message gets send before the SUBSCRIBED message (this is send after the on_create handler returns).

I changed the code so the on_create handler is called after the SUBSCRIBED message is send and it works. Here is the commit https://github.com/NomAnor/crossbar/commit/c5d2fa9a8f31e42d92f3674e8762ef5b088fa3ee?diff=unified

goeddea commented 9 years ago

@oberstet @meejah - could you take a look at this?

meejah commented 9 years ago

I can take a closer look in a couple hours, but from this description it definitely sounds like a bug I'd say; the meta-event shouldn't happen before we've successfully (fully) subscribed. Certainly sending events in a .on_create handler sounds reasonable to me.

oberstet commented 9 years ago

@NomAnor the proposed change doesn't achieve what you expect under all conditions, since the order in which events are published by Crossbar.io on 2 different WAMP connections does not necessarily mean the events are received in that order (time) by the clients on those 2 connections. One connection might run over a very slow link.

The WAMP spec says this about ordering guarantees: https://github.com/tavendo/WAMP/blob/master/spec/basic.md#ordering-guarantees

The WAMP AP (which defines WAMP meta events) however does not talk at all about ordering of meta events w.r.t. the underlying trigger. The spec should at least discuss it https://github.com/tavendo/WAMP/issues/169

NomAnor commented 9 years ago

Further, if Subscriber A subscribes to Topic 1, the SUBSCRIBED message will be sent by Broker to Subscriber A before any EVENT message for Topic 1.

This seems not to be true for crossbar. My JavaScript client subscribes to Topic A and receives an EVENT message for it before it receives the SUBSCRIBED message.

When I'm not mistaken there are three nodes im my case:

And then these events happen:

  1. B subscribes to wamp.subscription.on_create when crossbar starts.
  2. A subscribes to my.topic
  3. C publishes to wamp.subscription.on_create
  4. B publishes to my.topic
  5. A is subscribed to my.topic (SUBSCRIBED message)
  6. A receives EVENT message

With these pairings between Publisher and Subscriber:

Event 1 happens at startup before any client connects, so this can be ignored. Event 2 happens before all following events. The Events 3, 4 and 5 can happen in any order and with any delay. Event 6 is guaranteed (by Spec) to happen after Event 5.

What I see is that if Event 4 happens before Event 5 then the guarantee is broken. The code change prevents this but this could only be in my case where there is no delay between Event 3 and 4 (because my python code runs as a container in crossbar).

If Event 4 happens before Event 5 then A should not receive an EVENT message at all because it is not yet subscribed. In the current code, the subscription on the router is finished (all data structures are updated) but the SUBSCRIBED message is not send. So when a publish occurs in between (because of the meta event code and no delay because of the container) the router thinks the client is subscribed but the client is still waiting for the subscribtion to be finished.

The only problem is the ordering between the SUBSCRIBED and the EVENT message (for my.topic) and that ordering is guaranteed by the spec.

My publish is triggered by a callback run in another thread, but I use reactor.callFromThread(self.publish, uri, value) in this callback to be thread-safe. Maybe thats a problem?

Sorry for the wall of text.

oberstet commented 9 years ago

The only problem is the ordering between the SUBSCRIBED and the EVENT message (for my.topic) and that ordering is guaranteed by the spec.

Yes, correct. This is hence, indeed a bug in Crossbar.io.