message_bus 0.9.3.2 → 0.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of message_bus might be problematic. Click here for more details.
- checksums.yaml +4 -4
 - data/CHANGELOG +8 -0
 - data/Guardfile +1 -1
 - data/README.md +17 -0
 - data/assets/message-bus.js +1 -0
 - data/examples/minimal/Gemfile +3 -0
 - data/examples/minimal/config.ru +7 -0
 - data/lib/message_bus.rb +96 -29
 - data/lib/message_bus/client.rb +5 -4
 - data/lib/message_bus/connection_manager.rb +3 -2
 - data/lib/message_bus/rack/diagnostics.rb +6 -5
 - data/lib/message_bus/rack/middleware.rb +33 -22
 - data/lib/message_bus/reliable_pub_sub.rb +7 -1
 - data/lib/message_bus/version.rb +1 -1
 - data/spec/lib/connection_manager_spec.rb +2 -1
 - data/spec/lib/fake_async_middleware.rb +31 -22
 - data/spec/lib/message_bus_spec.rb +60 -0
 - data/spec/lib/middleware_spec.rb +99 -45
 - data/vendor/assets/javascripts/message-bus.js +1 -0
 - metadata +4 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: bd00357fe6b7e4663c46c3c34c74a5d8529433c5
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: df3641a9d63749c6035ecd0b45d656bd53361e4d
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: c08c802702acc7c30db0c3ebfb1c0949644553b7fc6a63330a8f260d414a350e94c2fb40143bd3956a068eda1a8e764e3fc3f858568bedb5075d25d82392185d
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 41c4d7584df49be995a21495841d63d65998aab5582c5ec6987fc620f86b995cc632e505fa641558c15568d8e6545075d075f4eec1c6501ad21fc4563220dc99
         
     | 
    
        data/CHANGELOG
    CHANGED
    
    | 
         @@ -1,3 +1,11 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            13-01-2014
         
     | 
| 
      
 2 
     | 
    
         
            +
            - Version 0.9.4
         
     | 
| 
      
 3 
     | 
    
         
            +
            - Added support for /global/ channel to publish messages across a multisite
         
     | 
| 
      
 4 
     | 
    
         
            +
            - Cleaned up test harness so it uses local bus as opposed to global
         
     | 
| 
      
 5 
     | 
    
         
            +
            - Fix bug where we could subscribe to a channel but miss starting messages
         
     | 
| 
      
 6 
     | 
    
         
            +
            - Added method for destroying a local MessageBus instance
         
     | 
| 
      
 7 
     | 
    
         
            +
            - ensure_reactor could say the reactor is running, but it was not, on first call
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
       1 
9 
     | 
    
         
             
            06-12-2013
         
     | 
| 
       2 
10 
     | 
    
         
             
            - Version 0.9.3.2
         
     | 
| 
       3 
11 
     | 
    
         
             
            - Fix permissions in gem
         
     | 
    
        data/Guardfile
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | 
         @@ -60,6 +60,23 @@ end 
     | 
|
| 
       60 
60 
     | 
    
         | 
| 
       61 
61 
     | 
    
         
             
            ```
         
     | 
| 
       62 
62 
     | 
    
         | 
| 
      
 63 
     | 
    
         
            +
            ### Multisite support
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
            MessageBus can be used in an environment that hosts multiple sites by multiplexing channels. To use this mode
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
            ```
         
     | 
| 
      
 68 
     | 
    
         
            +
            # define a site_id lookup method
         
     | 
| 
      
 69 
     | 
    
         
            +
            MessageBus.site_id_lookup do
         
     | 
| 
      
 70 
     | 
    
         
            +
              some_method_that_returns_site_id_string
         
     | 
| 
      
 71 
     | 
    
         
            +
            end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
            # you may post messages just to this site
         
     | 
| 
      
 74 
     | 
    
         
            +
            MessageBus.publish "/channel", "some message"
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
            # you may publish messages to ALL sites using the /global/ prefix
         
     | 
| 
      
 77 
     | 
    
         
            +
            MessageBus.publish "/global/channel", "will go to all sites"
         
     | 
| 
      
 78 
     | 
    
         
            +
            ```
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
       63 
80 
     | 
    
         
             
            JavaScript can listen on any channel (and receive notification via polling or long polling):
         
     | 
| 
       64 
81 
     | 
    
         | 
| 
       65 
82 
     | 
    
         
             
            ```html
         
     | 
    
        data/assets/message-bus.js
    CHANGED
    
    | 
         @@ -119,6 +119,7 @@ window.MessageBus = (function() { 
     | 
|
| 
       119 
119 
     | 
    
         
             
                  },
         
     | 
| 
       120 
120 
     | 
    
         
             
                  success: function(messages) {
         
     | 
| 
       121 
121 
     | 
    
         
             
                    failCount = 0;
         
     | 
| 
      
 122 
     | 
    
         
            +
                    if (messages === null) return; // server unexpectedly closed connection
         
     | 
| 
       122 
123 
     | 
    
         
             
                    $.each(messages,function(_,message) {
         
     | 
| 
       123 
124 
     | 
    
         
             
                      gotData = true;
         
     | 
| 
       124 
125 
     | 
    
         
             
                      $.each(callbacks, function(_,callback) {
         
     | 
    
        data/lib/message_bus.rb
    CHANGED
    
    | 
         @@ -12,6 +12,7 @@ require "message_bus/message_handler" 
     | 
|
| 
       12 
12 
     | 
    
         
             
            require "message_bus/diagnostics"
         
     | 
| 
       13 
13 
     | 
    
         
             
            require "message_bus/rack/middleware"
         
     | 
| 
       14 
14 
     | 
    
         
             
            require "message_bus/rack/diagnostics"
         
     | 
| 
      
 15 
     | 
    
         
            +
            require "monitor.rb"
         
     | 
| 
       15 
16 
     | 
    
         | 
| 
       16 
17 
     | 
    
         
             
            # we still need to take care of the logger
         
     | 
| 
       17 
18 
     | 
    
         
             
            if defined?(::Rails)
         
     | 
| 
         @@ -19,8 +20,20 @@ if defined?(::Rails) 
     | 
|
| 
       19 
20 
     | 
    
         
             
            end
         
     | 
| 
       20 
21 
     | 
    
         | 
| 
       21 
22 
     | 
    
         
             
            module MessageBus; end
         
     | 
| 
      
 23 
     | 
    
         
            +
            class MessageBus::InvalidMessage < Exception; end
         
     | 
| 
      
 24 
     | 
    
         
            +
            class MessageBus::BusDestroyed < Exception; end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
       22 
26 
     | 
    
         
             
            module MessageBus::Implementation
         
     | 
| 
       23 
27 
     | 
    
         | 
| 
      
 28 
     | 
    
         
            +
              # Like Mutex but safe for recursive calls
         
     | 
| 
      
 29 
     | 
    
         
            +
              class Synchronizer
         
     | 
| 
      
 30 
     | 
    
         
            +
                include MonitorMixin
         
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
              def initialize
         
     | 
| 
      
 34 
     | 
    
         
            +
                @mutex = Synchronizer.new
         
     | 
| 
      
 35 
     | 
    
         
            +
              end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
       24 
37 
     | 
    
         
             
              def cache_assets=(val)
         
     | 
| 
       25 
38 
     | 
    
         
             
                @cache_assets = val
         
     | 
| 
       26 
39 
     | 
    
         
             
              end
         
     | 
| 
         @@ -164,7 +177,10 @@ module MessageBus::Implementation 
     | 
|
| 
       164 
177 
     | 
    
         
             
              end
         
     | 
| 
       165 
178 
     | 
    
         | 
| 
       166 
179 
     | 
    
         
             
              def reliable_pub_sub
         
     | 
| 
       167 
     | 
    
         
            -
                @ 
     | 
| 
      
 180 
     | 
    
         
            +
                @mutex.synchronize do
         
     | 
| 
      
 181 
     | 
    
         
            +
                  return nil if @destroyed
         
     | 
| 
      
 182 
     | 
    
         
            +
                  @reliable_pub_sub ||= MessageBus::ReliablePubSub.new redis_config
         
     | 
| 
      
 183 
     | 
    
         
            +
                end
         
     | 
| 
       168 
184 
     | 
    
         
             
              end
         
     | 
| 
       169 
185 
     | 
    
         | 
| 
       170 
186 
     | 
    
         
             
              def enable_diagnostics
         
     | 
| 
         @@ -173,6 +189,9 @@ module MessageBus::Implementation 
     | 
|
| 
       173 
189 
     | 
    
         | 
| 
       174 
190 
     | 
    
         
             
              def publish(channel, data, opts = nil)
         
     | 
| 
       175 
191 
     | 
    
         
             
                return if @off
         
     | 
| 
      
 192 
     | 
    
         
            +
                @mutex.synchronize do
         
     | 
| 
      
 193 
     | 
    
         
            +
                  raise ::MessageBus::BusDestroyed if @destroyed
         
     | 
| 
      
 194 
     | 
    
         
            +
                end
         
     | 
| 
       176 
195 
     | 
    
         | 
| 
       177 
196 
     | 
    
         
             
                user_ids = nil
         
     | 
| 
       178 
197 
     | 
    
         
             
                group_ids = nil
         
     | 
| 
         @@ -181,6 +200,8 @@ module MessageBus::Implementation 
     | 
|
| 
       181 
200 
     | 
    
         
             
                  group_ids = opts[:group_ids]
         
     | 
| 
       182 
201 
     | 
    
         
             
                end
         
     | 
| 
       183 
202 
     | 
    
         | 
| 
      
 203 
     | 
    
         
            +
                raise ::MessageBus::InvalidMessage if (user_ids || group_ids) && global?(channel)
         
     | 
| 
      
 204 
     | 
    
         
            +
             
     | 
| 
       184 
205 
     | 
    
         
             
                encoded_data = JSON.dump({
         
     | 
| 
       185 
206 
     | 
    
         
             
                  data: data,
         
     | 
| 
       186 
207 
     | 
    
         
             
                  user_ids: user_ids,
         
     | 
| 
         @@ -202,7 +223,7 @@ module MessageBus::Implementation 
     | 
|
| 
       202 
223 
     | 
    
         | 
| 
       203 
224 
     | 
    
         
             
              # encode channel name to include site
         
     | 
| 
       204 
225 
     | 
    
         
             
              def encode_channel_name(channel)
         
     | 
| 
       205 
     | 
    
         
            -
                if site_id_lookup
         
     | 
| 
      
 226 
     | 
    
         
            +
                if site_id_lookup && !global?(channel)
         
     | 
| 
       206 
227 
     | 
    
         
             
                  raise ArgumentError.new channel if channel.include? ENCODE_SITE_TOKEN
         
     | 
| 
       207 
228 
     | 
    
         
             
                  "#{channel}#{ENCODE_SITE_TOKEN}#{site_id_lookup.call}"
         
     | 
| 
       208 
229 
     | 
    
         
             
                else
         
     | 
| 
         @@ -229,7 +250,7 @@ module MessageBus::Implementation 
     | 
|
| 
       229 
250 
     | 
    
         | 
| 
       230 
251 
     | 
    
         
             
              # subscribe only on current site
         
     | 
| 
       231 
252 
     | 
    
         
             
              def local_subscribe(channel=nil, &blk)
         
     | 
| 
       232 
     | 
    
         
            -
                site_id = site_id_lookup.call if site_id_lookup
         
     | 
| 
      
 253 
     | 
    
         
            +
                site_id = site_id_lookup.call if site_id_lookup && ! global?(channel)
         
     | 
| 
       233 
254 
     | 
    
         
             
                subscribe_impl(channel, site_id, &blk)
         
     | 
| 
       234 
255 
     | 
    
         
             
              end
         
     | 
| 
       235 
256 
     | 
    
         | 
| 
         @@ -238,7 +259,7 @@ module MessageBus::Implementation 
     | 
|
| 
       238 
259 
     | 
    
         
             
                  if channel
         
     | 
| 
       239 
260 
     | 
    
         
             
                    reliable_pub_sub.backlog(encode_channel_name(channel), last_id)
         
     | 
| 
       240 
261 
     | 
    
         
             
                  else
         
     | 
| 
       241 
     | 
    
         
            -
                    reliable_pub_sub.global_backlog( 
     | 
| 
      
 262 
     | 
    
         
            +
                    reliable_pub_sub.global_backlog(last_id)
         
     | 
| 
       242 
263 
     | 
    
         
             
                  end
         
     | 
| 
       243 
264 
     | 
    
         | 
| 
       244 
265 
     | 
    
         
             
                old.each{ |m|
         
     | 
| 
         @@ -247,14 +268,26 @@ module MessageBus::Implementation 
     | 
|
| 
       247 
268 
     | 
    
         
             
                old
         
     | 
| 
       248 
269 
     | 
    
         
             
              end
         
     | 
| 
       249 
270 
     | 
    
         | 
| 
       250 
     | 
    
         
            -
             
     | 
| 
       251 
271 
     | 
    
         
             
              def last_id(channel)
         
     | 
| 
       252 
272 
     | 
    
         
             
                reliable_pub_sub.last_id(encode_channel_name(channel))
         
     | 
| 
       253 
273 
     | 
    
         
             
              end
         
     | 
| 
       254 
274 
     | 
    
         | 
| 
      
 275 
     | 
    
         
            +
              def last_message(channel)
         
     | 
| 
      
 276 
     | 
    
         
            +
                if last_id = last_id(channel)
         
     | 
| 
      
 277 
     | 
    
         
            +
                  messages = backlog(channel, last_id-1)
         
     | 
| 
      
 278 
     | 
    
         
            +
                  if messages
         
     | 
| 
      
 279 
     | 
    
         
            +
                    messages[0]
         
     | 
| 
      
 280 
     | 
    
         
            +
                  end
         
     | 
| 
      
 281 
     | 
    
         
            +
                end
         
     | 
| 
      
 282 
     | 
    
         
            +
              end
         
     | 
| 
       255 
283 
     | 
    
         | 
| 
       256 
284 
     | 
    
         
             
              def destroy
         
     | 
| 
       257 
     | 
    
         
            -
                 
     | 
| 
      
 285 
     | 
    
         
            +
                @mutex.synchronize do
         
     | 
| 
      
 286 
     | 
    
         
            +
                  @subscriptions ||= {}
         
     | 
| 
      
 287 
     | 
    
         
            +
                  reliable_pub_sub.global_unsubscribe
         
     | 
| 
      
 288 
     | 
    
         
            +
                  @destroyed = true
         
     | 
| 
      
 289 
     | 
    
         
            +
                end
         
     | 
| 
      
 290 
     | 
    
         
            +
                @subscriber_thread.join if @subscriber_thread
         
     | 
| 
       258 
291 
     | 
    
         
             
              end
         
     | 
| 
       259 
292 
     | 
    
         | 
| 
       260 
293 
     | 
    
         
             
              def after_fork
         
     | 
| 
         @@ -262,8 +295,21 @@ module MessageBus::Implementation 
     | 
|
| 
       262 
295 
     | 
    
         
             
                ensure_subscriber_thread
         
     | 
| 
       263 
296 
     | 
    
         
             
              end
         
     | 
| 
       264 
297 
     | 
    
         | 
| 
      
 298 
     | 
    
         
            +
              def listening?
         
     | 
| 
      
 299 
     | 
    
         
            +
                @subscriber_thread && @subscriber_thread.alive?
         
     | 
| 
      
 300 
     | 
    
         
            +
              end
         
     | 
| 
      
 301 
     | 
    
         
            +
             
     | 
| 
      
 302 
     | 
    
         
            +
              # will reset all keys
         
     | 
| 
      
 303 
     | 
    
         
            +
              def reset!
         
     | 
| 
      
 304 
     | 
    
         
            +
                reliable_pub_sub.reset!
         
     | 
| 
      
 305 
     | 
    
         
            +
              end
         
     | 
| 
      
 306 
     | 
    
         
            +
             
     | 
| 
       265 
307 
     | 
    
         
             
              protected
         
     | 
| 
       266 
308 
     | 
    
         | 
| 
      
 309 
     | 
    
         
            +
              def global?(channel)
         
     | 
| 
      
 310 
     | 
    
         
            +
                channel && channel.start_with?('/global/'.freeze)
         
     | 
| 
      
 311 
     | 
    
         
            +
              end
         
     | 
| 
      
 312 
     | 
    
         
            +
             
     | 
| 
       267 
313 
     | 
    
         
             
              def decode_message!(msg)
         
     | 
| 
       268 
314 
     | 
    
         
             
                channel, site_id = decode_channel_name(msg.channel)
         
     | 
| 
       269 
315 
     | 
    
         
             
                msg.channel = channel
         
     | 
| 
         @@ -275,15 +321,27 @@ module MessageBus::Implementation 
     | 
|
| 
       275 
321 
     | 
    
         
             
              end
         
     | 
| 
       276 
322 
     | 
    
         | 
| 
       277 
323 
     | 
    
         
             
              def subscribe_impl(channel, site_id, &blk)
         
     | 
| 
      
 324 
     | 
    
         
            +
             
     | 
| 
      
 325 
     | 
    
         
            +
                raise MessageBus::BusDestroyed if @destroyed
         
     | 
| 
      
 326 
     | 
    
         
            +
             
     | 
| 
       278 
327 
     | 
    
         
             
                @subscriptions ||= {}
         
     | 
| 
       279 
328 
     | 
    
         
             
                @subscriptions[site_id] ||= {}
         
     | 
| 
       280 
329 
     | 
    
         
             
                @subscriptions[site_id][channel] ||=  []
         
     | 
| 
       281 
330 
     | 
    
         
             
                @subscriptions[site_id][channel] << blk
         
     | 
| 
       282 
331 
     | 
    
         
             
                ensure_subscriber_thread
         
     | 
| 
      
 332 
     | 
    
         
            +
             
     | 
| 
      
 333 
     | 
    
         
            +
                attempts = 100
         
     | 
| 
      
 334 
     | 
    
         
            +
                while attempts > 0 && !reliable_pub_sub.subscribed
         
     | 
| 
      
 335 
     | 
    
         
            +
                  sleep 0.001
         
     | 
| 
      
 336 
     | 
    
         
            +
                  attempts-=1
         
     | 
| 
      
 337 
     | 
    
         
            +
                end
         
     | 
| 
      
 338 
     | 
    
         
            +
             
     | 
| 
      
 339 
     | 
    
         
            +
                raise MessageBus::BusDestroyed if @destroyed
         
     | 
| 
       283 
340 
     | 
    
         
             
                blk
         
     | 
| 
       284 
341 
     | 
    
         
             
              end
         
     | 
| 
       285 
342 
     | 
    
         | 
| 
       286 
343 
     | 
    
         
             
              def unsubscribe_impl(channel, site_id, &blk)
         
     | 
| 
      
 344 
     | 
    
         
            +
             
     | 
| 
       287 
345 
     | 
    
         
             
                @mutex.synchronize do
         
     | 
| 
       288 
346 
     | 
    
         
             
                  if blk
         
     | 
| 
       289 
347 
     | 
    
         
             
                    @subscriptions[site_id][channel].delete blk
         
     | 
| 
         @@ -291,42 +349,50 @@ module MessageBus::Implementation 
     | 
|
| 
       291 
349 
     | 
    
         
             
                    @subscriptions[site_id][channel] = []
         
     | 
| 
       292 
350 
     | 
    
         
             
                  end
         
     | 
| 
       293 
351 
     | 
    
         
             
                end
         
     | 
| 
      
 352 
     | 
    
         
            +
             
     | 
| 
       294 
353 
     | 
    
         
             
              end
         
     | 
| 
       295 
354 
     | 
    
         | 
| 
       296 
355 
     | 
    
         | 
| 
       297 
356 
     | 
    
         
             
              def ensure_subscriber_thread
         
     | 
| 
       298 
     | 
    
         
            -
                @mutex ||= Mutex.new
         
     | 
| 
       299 
357 
     | 
    
         
             
                @mutex.synchronize do
         
     | 
| 
       300 
     | 
    
         
            -
                  return if @subscriber_thread && @subscriber_thread.alive?
         
     | 
| 
       301 
     | 
    
         
            -
                  @subscriber_thread =  
     | 
| 
       302 
     | 
    
         
            -
             
     | 
| 
       303 
     | 
    
         
            -
             
     | 
| 
       304 
     | 
    
         
            -
                        decode_message!(msg)
         
     | 
| 
      
 358 
     | 
    
         
            +
                  return if (@subscriber_thread && @subscriber_thread.alive?) || @destroyed
         
     | 
| 
      
 359 
     | 
    
         
            +
                  @subscriber_thread = new_subscriber_thread
         
     | 
| 
      
 360 
     | 
    
         
            +
                end
         
     | 
| 
      
 361 
     | 
    
         
            +
              end
         
     | 
| 
       305 
362 
     | 
    
         | 
| 
       306 
     | 
    
         
            -
             
     | 
| 
       307 
     | 
    
         
            -
             
     | 
| 
       308 
     | 
    
         
            -
             
     | 
| 
      
 363 
     | 
    
         
            +
              def new_subscriber_thread
         
     | 
| 
      
 364 
     | 
    
         
            +
                Thread.new do
         
     | 
| 
      
 365 
     | 
    
         
            +
                  global_subscribe_thread unless @destroyed
         
     | 
| 
      
 366 
     | 
    
         
            +
                end
         
     | 
| 
      
 367 
     | 
    
         
            +
              end
         
     | 
| 
       309 
368 
     | 
    
         | 
| 
       310 
     | 
    
         
            -
             
     | 
| 
       311 
     | 
    
         
            -
             
     | 
| 
      
 369 
     | 
    
         
            +
              def global_subscribe_thread
         
     | 
| 
      
 370 
     | 
    
         
            +
                reliable_pub_sub.global_subscribe do |msg|
         
     | 
| 
      
 371 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 372 
     | 
    
         
            +
                    decode_message!(msg)
         
     | 
| 
      
 373 
     | 
    
         
            +
                    globals, locals, local_globals, global_globals = nil
         
     | 
| 
       312 
374 
     | 
    
         | 
| 
       313 
     | 
    
         
            -
             
     | 
| 
       314 
     | 
    
         
            -
             
     | 
| 
      
 375 
     | 
    
         
            +
                    @mutex.synchronize do
         
     | 
| 
      
 376 
     | 
    
         
            +
                      raise MessageBus::BusDestroyed if @destroyed
         
     | 
| 
      
 377 
     | 
    
         
            +
                      globals = @subscriptions[nil]
         
     | 
| 
      
 378 
     | 
    
         
            +
                      locals = @subscriptions[msg.site_id] if msg.site_id
         
     | 
| 
       315 
379 
     | 
    
         | 
| 
       316 
     | 
    
         
            -
             
     | 
| 
       317 
     | 
    
         
            -
             
     | 
| 
       318 
     | 
    
         
            -
                              c.call msg
         
     | 
| 
       319 
     | 
    
         
            -
                            rescue => e
         
     | 
| 
       320 
     | 
    
         
            -
                              MessageBus.logger.warn "failed to deliver message, skipping #{msg.inspect}\n ex: #{e} backtrace: #{e.backtrace}"
         
     | 
| 
       321 
     | 
    
         
            -
                            end
         
     | 
| 
       322 
     | 
    
         
            -
                          end
         
     | 
| 
       323 
     | 
    
         
            -
                        end
         
     | 
| 
      
 380 
     | 
    
         
            +
                      global_globals = globals[nil] if globals
         
     | 
| 
      
 381 
     | 
    
         
            +
                      local_globals = locals[nil] if locals
         
     | 
| 
       324 
382 
     | 
    
         | 
| 
      
 383 
     | 
    
         
            +
                      globals = globals[msg.channel] if globals
         
     | 
| 
      
 384 
     | 
    
         
            +
                      locals = locals[msg.channel] if locals
         
     | 
| 
      
 385 
     | 
    
         
            +
                    end
         
     | 
| 
      
 386 
     | 
    
         
            +
             
     | 
| 
      
 387 
     | 
    
         
            +
                    multi_each(globals,locals, global_globals, local_globals) do |c|
         
     | 
| 
      
 388 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 389 
     | 
    
         
            +
                        c.call msg
         
     | 
| 
       325 
390 
     | 
    
         
             
                      rescue => e
         
     | 
| 
       326 
     | 
    
         
            -
                        MessageBus.logger.warn "failed to  
     | 
| 
      
 391 
     | 
    
         
            +
                        MessageBus.logger.warn "failed to deliver message, skipping #{msg.inspect}\n ex: #{e} backtrace: #{e.backtrace}"
         
     | 
| 
       327 
392 
     | 
    
         
             
                      end
         
     | 
| 
       328 
     | 
    
         
            -
             
     | 
| 
       329 
393 
     | 
    
         
             
                    end
         
     | 
| 
      
 394 
     | 
    
         
            +
                  rescue => e
         
     | 
| 
      
 395 
     | 
    
         
            +
                    MessageBus.logger.warn "failed to process message #{msg.inspect}\n ex: #{e} backtrace: #{e.backtrace}"
         
     | 
| 
       330 
396 
     | 
    
         
             
                  end
         
     | 
| 
       331 
397 
     | 
    
         
             
                end
         
     | 
| 
       332 
398 
     | 
    
         
             
              end
         
     | 
| 
         @@ -341,6 +407,7 @@ end 
     | 
|
| 
       341 
407 
     | 
    
         | 
| 
       342 
408 
     | 
    
         
             
            module MessageBus
         
     | 
| 
       343 
409 
     | 
    
         
             
              extend MessageBus::Implementation
         
     | 
| 
      
 410 
     | 
    
         
            +
              initialize
         
     | 
| 
       344 
411 
     | 
    
         
             
            end
         
     | 
| 
       345 
412 
     | 
    
         | 
| 
       346 
413 
     | 
    
         
             
            # allows for multiple buses per app
         
     | 
    
        data/lib/message_bus/client.rb
    CHANGED
    
    | 
         @@ -6,6 +6,7 @@ class MessageBus::Client 
     | 
|
| 
       6 
6 
     | 
    
         
             
                self.group_ids = opts[:group_ids] || []
         
     | 
| 
       7 
7 
     | 
    
         
             
                self.site_id = opts[:site_id]
         
     | 
| 
       8 
8 
     | 
    
         
             
                self.connect_time = Time.now
         
     | 
| 
      
 9 
     | 
    
         
            +
                @bus = opts[:message_bus] || MessageBus
         
     | 
| 
       9 
10 
     | 
    
         
             
                @subscriptions = {}
         
     | 
| 
       10 
11 
     | 
    
         
             
              end
         
     | 
| 
       11 
12 
     | 
    
         | 
| 
         @@ -33,7 +34,7 @@ class MessageBus::Client 
     | 
|
| 
       33 
34 
     | 
    
         | 
| 
       34 
35 
     | 
    
         
             
              def subscribe(channel, last_seen_id)
         
     | 
| 
       35 
36 
     | 
    
         
             
                last_seen_id = nil if last_seen_id == ""
         
     | 
| 
       36 
     | 
    
         
            -
                last_seen_id ||=  
     | 
| 
      
 37 
     | 
    
         
            +
                last_seen_id ||= @bus.last_id(channel)
         
     | 
| 
       37 
38 
     | 
    
         
             
                @subscriptions[channel] = last_seen_id.to_i
         
     | 
| 
       38 
39 
     | 
    
         
             
              end
         
     | 
| 
       39 
40 
     | 
    
         | 
| 
         @@ -61,7 +62,7 @@ class MessageBus::Client 
     | 
|
| 
       61 
62 
     | 
    
         
             
              end
         
     | 
| 
       62 
63 
     | 
    
         | 
| 
       63 
64 
     | 
    
         
             
              def filter(msg)
         
     | 
| 
       64 
     | 
    
         
            -
                filter =  
     | 
| 
      
 65 
     | 
    
         
            +
                filter = @bus.client_filter(msg.channel)
         
     | 
| 
       65 
66 
     | 
    
         | 
| 
       66 
67 
     | 
    
         
             
                if filter
         
     | 
| 
       67 
68 
     | 
    
         
             
                  filter.call(self.user_id, msg)
         
     | 
| 
         @@ -74,7 +75,7 @@ class MessageBus::Client 
     | 
|
| 
       74 
75 
     | 
    
         
             
                r = []
         
     | 
| 
       75 
76 
     | 
    
         
             
                @subscriptions.each do |k,v|
         
     | 
| 
       76 
77 
     | 
    
         
             
                  next if v.to_i < 0
         
     | 
| 
       77 
     | 
    
         
            -
                  messages =  
     | 
| 
      
 78 
     | 
    
         
            +
                  messages = @bus.backlog(k,v)
         
     | 
| 
       78 
79 
     | 
    
         
             
                  messages.each do |msg|
         
     | 
| 
       79 
80 
     | 
    
         
             
                    r << msg if allowed?(msg)
         
     | 
| 
       80 
81 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -84,7 +85,7 @@ class MessageBus::Client 
     | 
|
| 
       84 
85 
     | 
    
         
             
                @subscriptions.each do |k,v|
         
     | 
| 
       85 
86 
     | 
    
         
             
                  if v.to_i == -1
         
     | 
| 
       86 
87 
     | 
    
         
             
                    status_message ||= {}
         
     | 
| 
       87 
     | 
    
         
            -
                    status_message[k] =  
     | 
| 
      
 88 
     | 
    
         
            +
                    status_message[k] = @bus.last_id(k)
         
     | 
| 
       88 
89 
     | 
    
         
             
                  end
         
     | 
| 
       89 
90 
     | 
    
         
             
                end
         
     | 
| 
       90 
91 
     | 
    
         
             
                r << MessageBus::Message.new(-1, -1, '/__status', status_message) if status_message
         
     | 
| 
         @@ -2,9 +2,10 @@ require 'json' unless defined? ::JSON 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            class MessageBus::ConnectionManager
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
     | 
    
         
            -
              def initialize
         
     | 
| 
      
 5 
     | 
    
         
            +
              def initialize(bus = nil)
         
     | 
| 
       6 
6 
     | 
    
         
             
                @clients = {}
         
     | 
| 
       7 
7 
     | 
    
         
             
                @subscriptions = {}
         
     | 
| 
      
 8 
     | 
    
         
            +
                @bus = bus || MessageBus
         
     | 
| 
       8 
9 
     | 
    
         
             
              end
         
     | 
| 
       9 
10 
     | 
    
         | 
| 
       10 
11 
     | 
    
         
             
              def notify_clients(msg)
         
     | 
| 
         @@ -14,7 +15,7 @@ class MessageBus::ConnectionManager 
     | 
|
| 
       14 
15 
     | 
    
         | 
| 
       15 
16 
     | 
    
         
             
                  return unless subscription
         
     | 
| 
       16 
17 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
                  around_filter =  
     | 
| 
      
 18 
     | 
    
         
            +
                  around_filter = @bus.around_client_batch(msg.channel)
         
     | 
| 
       18 
19 
     | 
    
         | 
| 
       19 
20 
     | 
    
         
             
                  work = lambda do
         
     | 
| 
       20 
21 
     | 
    
         
             
                    subscription.each do |client_id|
         
     | 
| 
         @@ -3,10 +3,11 @@ module MessageBus::Rack; end 
     | 
|
| 
       3 
3 
     | 
    
         
             
            class MessageBus::Rack::Diagnostics
         
     | 
| 
       4 
4 
     | 
    
         
             
              def initialize(app, config = {})
         
     | 
| 
       5 
5 
     | 
    
         
             
                @app = app
         
     | 
| 
      
 6 
     | 
    
         
            +
                @bus = config[:message_bus] || MessageBus
         
     | 
| 
       6 
7 
     | 
    
         
             
              end
         
     | 
| 
       7 
8 
     | 
    
         | 
| 
       8 
9 
     | 
    
         
             
              def js_asset(name)
         
     | 
| 
       9 
     | 
    
         
            -
                return generate_script_tag(name) unless  
     | 
| 
      
 10 
     | 
    
         
            +
                return generate_script_tag(name) unless @bus.cache_assets
         
     | 
| 
       10 
11 
     | 
    
         
             
                @@asset_cache ||= {}
         
     | 
| 
       11 
12 
     | 
    
         
             
                @@asset_cache[name] ||= generate_script_tag(name)
         
     | 
| 
       12 
13 
     | 
    
         
             
                @@asset_cache[name]
         
     | 
| 
         @@ -65,21 +66,21 @@ HTML 
     | 
|
| 
       65 
66 
     | 
    
         | 
| 
       66 
67 
     | 
    
         
             
                route = env['PATH_INFO'].split('/message-bus/_diagnostics')[1]
         
     | 
| 
       67 
68 
     | 
    
         | 
| 
       68 
     | 
    
         
            -
                if  
     | 
| 
      
 69 
     | 
    
         
            +
                if @bus.is_admin_lookup.nil? || !@bus.is_admin_lookup.call(env)
         
     | 
| 
       69 
70 
     | 
    
         
             
                  return [403, {}, ['not allowed']]
         
     | 
| 
       70 
71 
     | 
    
         
             
                end
         
     | 
| 
       71 
72 
     | 
    
         | 
| 
       72 
73 
     | 
    
         
             
                return index unless route
         
     | 
| 
       73 
74 
     | 
    
         | 
| 
       74 
75 
     | 
    
         
             
                if route == '/discover'
         
     | 
| 
       75 
     | 
    
         
            -
                  user_id = 
     | 
| 
       76 
     | 
    
         
            -
                   
     | 
| 
      
 76 
     | 
    
         
            +
                  user_id = @bus.user_id_lookup.call(env)
         
     | 
| 
      
 77 
     | 
    
         
            +
                  @bus.publish('/_diagnostics/discover', user_id: user_id)
         
     | 
| 
       77 
78 
     | 
    
         
             
                  return [200, {}, ['ok']]
         
     | 
| 
       78 
79 
     | 
    
         
             
                end
         
     | 
| 
       79 
80 
     | 
    
         | 
| 
       80 
81 
     | 
    
         
             
                if route =~ /^\/hup\//
         
     | 
| 
       81 
82 
     | 
    
         
             
                  hostname, pid = route.split('/hup/')[1].split('/')
         
     | 
| 
       82 
     | 
    
         
            -
                   
     | 
| 
      
 83 
     | 
    
         
            +
                  @bus.publish('/_diagnostics/hup', {hostname: hostname, pid: pid.to_i})
         
     | 
| 
       83 
84 
     | 
    
         
             
                  return [200, {}, ['ok']]
         
     | 
| 
       84 
85 
     | 
    
         
             
                end
         
     | 
| 
       85 
86 
     | 
    
         | 
| 
         @@ -3,19 +3,19 @@ module MessageBus::Rack; end 
     | 
|
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            class MessageBus::Rack::Middleware
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
     | 
    
         
            -
              def  
     | 
| 
      
 6 
     | 
    
         
            +
              def start_listener
         
     | 
| 
       7 
7 
     | 
    
         
             
                unless @started_listener
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
                  require 'eventmachine'
         
     | 
| 
       10 
10 
     | 
    
         
             
                  require 'message_bus/em_ext'
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
                   
     | 
| 
      
 12 
     | 
    
         
            +
                  @subscription = @bus.subscribe do |msg|
         
     | 
| 
       13 
13 
     | 
    
         
             
                    if EM.reactor_running?
         
     | 
| 
       14 
14 
     | 
    
         
             
                      EM.next_tick do
         
     | 
| 
       15 
15 
     | 
    
         
             
                        begin
         
     | 
| 
       16 
     | 
    
         
            -
                           
     | 
| 
      
 16 
     | 
    
         
            +
                          @connection_manager.notify_clients(msg) if @connection_manager
         
     | 
| 
       17 
17 
     | 
    
         
             
                        rescue
         
     | 
| 
       18 
     | 
    
         
            -
                           
     | 
| 
      
 18 
     | 
    
         
            +
                          @bus.logger.warn "Failed to notify clients: #{$!} #{$!.backtrace}"
         
     | 
| 
       19 
19 
     | 
    
         
             
                        end
         
     | 
| 
       20 
20 
     | 
    
         
             
                      end
         
     | 
| 
       21 
21 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -26,8 +26,16 @@ class MessageBus::Rack::Middleware 
     | 
|
| 
       26 
26 
     | 
    
         | 
| 
       27 
27 
     | 
    
         
             
              def initialize(app, config = {})
         
     | 
| 
       28 
28 
     | 
    
         
             
                @app = app
         
     | 
| 
       29 
     | 
    
         
            -
                 
     | 
| 
       30 
     | 
    
         
            -
                 
     | 
| 
      
 29 
     | 
    
         
            +
                @bus = config[:message_bus] || MessageBus
         
     | 
| 
      
 30 
     | 
    
         
            +
                @connection_manager = MessageBus::ConnectionManager.new(@bus)
         
     | 
| 
      
 31 
     | 
    
         
            +
                self.start_listener
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
              def stop_listener
         
     | 
| 
      
 35 
     | 
    
         
            +
                if @subscription
         
     | 
| 
      
 36 
     | 
    
         
            +
                  @bus.unsubscribe(&@subscription)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  @started_listener = false
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
       31 
39 
     | 
    
         
             
              end
         
     | 
| 
       32 
40 
     | 
    
         | 
| 
       33 
41 
     | 
    
         
             
              def self.backlog_to_json(backlog)
         
     | 
| 
         @@ -47,25 +55,25 @@ class MessageBus::Rack::Middleware 
     | 
|
| 
       47 
55 
     | 
    
         
             
                return @app.call(env) unless env['PATH_INFO'] =~ /^\/message-bus\//
         
     | 
| 
       48 
56 
     | 
    
         | 
| 
       49 
57 
     | 
    
         
             
                # special debug/test route
         
     | 
| 
       50 
     | 
    
         
            -
                if  
     | 
| 
      
 58 
     | 
    
         
            +
                if @bus.allow_broadcast? && env['PATH_INFO'] == '/message-bus/broadcast'.freeze
         
     | 
| 
       51 
59 
     | 
    
         
             
                    parsed = Rack::Request.new(env)
         
     | 
| 
       52 
     | 
    
         
            -
                     
     | 
| 
      
 60 
     | 
    
         
            +
                    @bus.publish parsed["channel".freeze], parsed["data".freeze]
         
     | 
| 
       53 
61 
     | 
    
         
             
                    return [200,{"Content-Type".freeze => "text/html".freeze},["sent"]]
         
     | 
| 
       54 
62 
     | 
    
         
             
                end
         
     | 
| 
       55 
63 
     | 
    
         | 
| 
       56 
64 
     | 
    
         
             
                if env['PATH_INFO'].start_with? '/message-bus/_diagnostics'.freeze
         
     | 
| 
       57 
     | 
    
         
            -
                  diags = MessageBus::Rack::Diagnostics.new(@app)
         
     | 
| 
      
 65 
     | 
    
         
            +
                  diags = MessageBus::Rack::Diagnostics.new(@app, message_bus: @bus)
         
     | 
| 
       58 
66 
     | 
    
         
             
                  return diags.call(env)
         
     | 
| 
       59 
67 
     | 
    
         
             
                end
         
     | 
| 
       60 
68 
     | 
    
         | 
| 
       61 
69 
     | 
    
         
             
                client_id = env['PATH_INFO'].split("/")[2]
         
     | 
| 
       62 
70 
     | 
    
         
             
                return [404, {}, ["not found"]] unless client_id
         
     | 
| 
       63 
71 
     | 
    
         | 
| 
       64 
     | 
    
         
            -
                user_id =  
     | 
| 
       65 
     | 
    
         
            -
                group_ids =  
     | 
| 
       66 
     | 
    
         
            -
                site_id =  
     | 
| 
      
 72 
     | 
    
         
            +
                user_id = @bus.user_id_lookup.call(env) if @bus.user_id_lookup
         
     | 
| 
      
 73 
     | 
    
         
            +
                group_ids = @bus.group_ids_lookup.call(env) if @bus.group_ids_lookup
         
     | 
| 
      
 74 
     | 
    
         
            +
                site_id = @bus.site_id_lookup.call(env) if @bus.site_id_lookup
         
     | 
| 
       67 
75 
     | 
    
         | 
| 
       68 
     | 
    
         
            -
                client = MessageBus::Client.new(client_id: client_id, user_id: user_id, site_id: site_id, group_ids: group_ids)
         
     | 
| 
      
 76 
     | 
    
         
            +
                client = MessageBus::Client.new(message_bus: @bus, client_id: client_id, user_id: user_id, site_id: site_id, group_ids: group_ids)
         
     | 
| 
       69 
77 
     | 
    
         | 
| 
       70 
78 
     | 
    
         
             
                request = Rack::Request.new(env)
         
     | 
| 
       71 
79 
     | 
    
         
             
                request.POST.each do |k,v|
         
     | 
| 
         @@ -79,22 +87,20 @@ class MessageBus::Rack::Middleware 
     | 
|
| 
       79 
87 
     | 
    
         | 
| 
       80 
88 
     | 
    
         
             
                ensure_reactor
         
     | 
| 
       81 
89 
     | 
    
         | 
| 
       82 
     | 
    
         
            -
                long_polling =  
     | 
| 
      
 90 
     | 
    
         
            +
                long_polling = @bus.long_polling_enabled? &&
         
     | 
| 
       83 
91 
     | 
    
         
             
                               env['QUERY_STRING'] !~ /dlp=t/.freeze &&
         
     | 
| 
       84 
92 
     | 
    
         
             
                               EM.reactor_running? &&
         
     | 
| 
       85 
     | 
    
         
            -
                                
     | 
| 
      
 93 
     | 
    
         
            +
                               @connection_manager.client_count < @bus.max_active_clients
         
     | 
| 
       86 
94 
     | 
    
         | 
| 
       87 
     | 
    
         
            -
                #STDERR.puts "LONG POLLING  lp enabled #{MessageBus.long_polling_enabled?}, reactor #{EM.reactor_running?} count: #{@@connection_manager.client_count} ,  active #{MessageBus.max_active_clients} #{long_polling}"
         
     | 
| 
       88 
95 
     | 
    
         
             
                if backlog.length > 0
         
     | 
| 
       89 
96 
     | 
    
         
             
                  [200, headers, [self.class.backlog_to_json(backlog)] ]
         
     | 
| 
       90 
     | 
    
         
            -
                elsif long_polling && env['rack.hijack'] &&  
     | 
| 
      
 97 
     | 
    
         
            +
                elsif long_polling && env['rack.hijack'] && @bus.rack_hijack_enabled?
         
     | 
| 
       91 
98 
     | 
    
         
             
                  io = env['rack.hijack'].call
         
     | 
| 
       92 
99 
     | 
    
         
             
                  client.io = io
         
     | 
| 
       93 
100 
     | 
    
         | 
| 
       94 
101 
     | 
    
         
             
                  add_client_with_timeout(client)
         
     | 
| 
       95 
102 
     | 
    
         
             
                  [418, {}, ["I'm a teapot, undefined in spec"]]
         
     | 
| 
       96 
103 
     | 
    
         
             
                elsif long_polling && env['async.callback']
         
     | 
| 
       97 
     | 
    
         
            -
             
     | 
| 
       98 
104 
     | 
    
         
             
                  response = nil
         
     | 
| 
       99 
105 
     | 
    
         
             
                  # load extension if needed
         
     | 
| 
       100 
106 
     | 
    
         
             
                  begin
         
     | 
| 
         @@ -122,19 +128,24 @@ class MessageBus::Rack::Middleware 
     | 
|
| 
       122 
128 
     | 
    
         
             
                # ensure reactor is running
         
     | 
| 
       123 
129 
     | 
    
         
             
                if EM.reactor_pid != Process.pid
         
     | 
| 
       124 
130 
     | 
    
         
             
                  Thread.new { EM.run }
         
     | 
| 
      
 131 
     | 
    
         
            +
                  i = 100
         
     | 
| 
      
 132 
     | 
    
         
            +
                  while !EM.reactor_running? && i > 0
         
     | 
| 
      
 133 
     | 
    
         
            +
                    sleep 0.001
         
     | 
| 
      
 134 
     | 
    
         
            +
                    i -= 1
         
     | 
| 
      
 135 
     | 
    
         
            +
                  end
         
     | 
| 
       125 
136 
     | 
    
         
             
                end
         
     | 
| 
       126 
137 
     | 
    
         
             
              end
         
     | 
| 
       127 
138 
     | 
    
         | 
| 
       128 
139 
     | 
    
         
             
              def add_client_with_timeout(client)
         
     | 
| 
       129 
     | 
    
         
            -
                 
     | 
| 
      
 140 
     | 
    
         
            +
                @connection_manager.add_client(client)
         
     | 
| 
       130 
141 
     | 
    
         | 
| 
       131 
     | 
    
         
            -
                client.cleanup_timer = ::EM::Timer.new( 
     | 
| 
      
 142 
     | 
    
         
            +
                client.cleanup_timer = ::EM::Timer.new( @bus.long_polling_interval.to_f / 1000) {
         
     | 
| 
       132 
143 
     | 
    
         
             
                  begin
         
     | 
| 
       133 
144 
     | 
    
         
             
                    client.cleanup_timer = nil
         
     | 
| 
       134 
145 
     | 
    
         
             
                    client.ensure_closed!
         
     | 
| 
       135 
     | 
    
         
            -
                     
     | 
| 
      
 146 
     | 
    
         
            +
                    @connection_manager.remove_client(client)
         
     | 
| 
       136 
147 
     | 
    
         
             
                  rescue
         
     | 
| 
       137 
     | 
    
         
            -
                     
     | 
| 
      
 148 
     | 
    
         
            +
                    @bus.logger.warn "Failed to clean up client properly: #{$!} #{$!.backtrace}"
         
     | 
| 
       138 
149 
     | 
    
         
             
                  end
         
     | 
| 
       139 
150 
     | 
    
         
             
                }
         
     | 
| 
       140 
151 
     | 
    
         
             
              end
         
     | 
| 
         @@ -9,6 +9,7 @@ require 'redis' 
     | 
|
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         
             
            class MessageBus::ReliablePubSub
         
     | 
| 
      
 12 
     | 
    
         
            +
              attr_reader :subscribed
         
     | 
| 
       12 
13 
     | 
    
         | 
| 
       13 
14 
     | 
    
         
             
              UNSUB_MESSAGE = "$$UNSUBSCRIBE"
         
     | 
| 
       14 
15 
     | 
    
         | 
| 
         @@ -212,7 +213,6 @@ class MessageBus::ReliablePubSub 
     | 
|
| 
       212 
213 
     | 
    
         
             
              end
         
     | 
| 
       213 
214 
     | 
    
         | 
| 
       214 
215 
     | 
    
         
             
              def global_unsubscribe
         
     | 
| 
       215 
     | 
    
         
            -
                # TODO mutex
         
     | 
| 
       216 
216 
     | 
    
         
             
                if @redis_global
         
     | 
| 
       217 
217 
     | 
    
         
             
                  pub_redis.publish(redis_channel_name, UNSUB_MESSAGE)
         
     | 
| 
       218 
218 
     | 
    
         
             
                  @redis_global.disconnect
         
     | 
| 
         @@ -249,7 +249,13 @@ class MessageBus::ReliablePubSub 
     | 
|
| 
       249 
249 
     | 
    
         
             
                      if highest_id
         
     | 
| 
       250 
250 
     | 
    
         
             
                        clear_backlog.call(&blk)
         
     | 
| 
       251 
251 
     | 
    
         
             
                      end
         
     | 
| 
      
 252 
     | 
    
         
            +
                      @subscribed = true
         
     | 
| 
       252 
253 
     | 
    
         
             
                    end
         
     | 
| 
      
 254 
     | 
    
         
            +
             
     | 
| 
      
 255 
     | 
    
         
            +
                    on.unsubscribe do
         
     | 
| 
      
 256 
     | 
    
         
            +
                      @subscribed = false
         
     | 
| 
      
 257 
     | 
    
         
            +
                    end
         
     | 
| 
      
 258 
     | 
    
         
            +
             
     | 
| 
       253 
259 
     | 
    
         
             
                    on.message do |c,m|
         
     | 
| 
       254 
260 
     | 
    
         
             
                      if m == UNSUB_MESSAGE
         
     | 
| 
       255 
261 
     | 
    
         
             
                        @redis_global.unsubscribe
         
     | 
    
        data/lib/message_bus/version.rb
    CHANGED
    
    
| 
         @@ -23,7 +23,8 @@ end 
     | 
|
| 
       23 
23 
     | 
    
         
             
            describe MessageBus::ConnectionManager do
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
       25 
25 
     | 
    
         
             
              before do
         
     | 
| 
       26 
     | 
    
         
            -
                @ 
     | 
| 
      
 26 
     | 
    
         
            +
                @bus = MessageBus
         
     | 
| 
      
 27 
     | 
    
         
            +
                @manager = MessageBus::ConnectionManager.new(@bus)
         
     | 
| 
       27 
28 
     | 
    
         
             
                @client = MessageBus::Client.new(client_id: "xyz", user_id: 1, site_id: 10)
         
     | 
| 
       28 
29 
     | 
    
         
             
                @resp = FakeAsync.new
         
     | 
| 
       29 
30 
     | 
    
         
             
                @client.async_response = @resp
         
     | 
| 
         @@ -1,38 +1,47 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'http/parser'
         
     | 
| 
       2 
2 
     | 
    
         
             
            class FakeAsyncMiddleware
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
     | 
    
         
            -
              def  
     | 
| 
       5 
     | 
    
         
            -
                 
     | 
| 
       6 
     | 
    
         
            -
                 
     | 
| 
      
 4 
     | 
    
         
            +
              def initialize(app,config={})
         
     | 
| 
      
 5 
     | 
    
         
            +
                @app = app
         
     | 
| 
      
 6 
     | 
    
         
            +
                @bus = config[:message_bus] || MessageBus
         
     | 
| 
      
 7 
     | 
    
         
            +
                @simulate_thin_async = false
         
     | 
| 
      
 8 
     | 
    
         
            +
                @simulate_hijack = false
         
     | 
| 
      
 9 
     | 
    
         
            +
                @in_async = false
         
     | 
| 
       7 
10 
     | 
    
         
             
              end
         
     | 
| 
       8 
11 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
              def  
     | 
| 
       10 
     | 
    
         
            -
                 
     | 
| 
       11 
     | 
    
         
            -
                @@simulate_hijack = true
         
     | 
| 
      
 12 
     | 
    
         
            +
              def app
         
     | 
| 
      
 13 
     | 
    
         
            +
                @app
         
     | 
| 
       12 
14 
     | 
    
         
             
              end
         
     | 
| 
       13 
15 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
              def  
     | 
| 
       15 
     | 
    
         
            -
                 
     | 
| 
      
 16 
     | 
    
         
            +
              def simulate_thin_async
         
     | 
| 
      
 17 
     | 
    
         
            +
                @simulate_thin_async = true
         
     | 
| 
      
 18 
     | 
    
         
            +
                @simulate_hijack = false
         
     | 
| 
       16 
19 
     | 
    
         
             
              end
         
     | 
| 
       17 
20 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
              def  
     | 
| 
       19 
     | 
    
         
            -
                @ 
     | 
| 
      
 21 
     | 
    
         
            +
              def simulate_hijack
         
     | 
| 
      
 22 
     | 
    
         
            +
                @simulate_thin_async = false
         
     | 
| 
      
 23 
     | 
    
         
            +
                @simulate_hijack = true
         
     | 
| 
       20 
24 
     | 
    
         
             
              end
         
     | 
| 
       21 
25 
     | 
    
         | 
| 
       22 
     | 
    
         
            -
              def  
     | 
| 
       23 
     | 
    
         
            -
                 
     | 
| 
      
 26 
     | 
    
         
            +
              def in_async?
         
     | 
| 
      
 27 
     | 
    
         
            +
                @in_async
         
     | 
| 
       24 
28 
     | 
    
         
             
              end
         
     | 
| 
       25 
29 
     | 
    
         | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              def simulate_thin_async?
         
     | 
| 
      
 32 
     | 
    
         
            +
                @simulate_thin_async && @bus.long_polling_enabled?
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              def simulate_hijack?
         
     | 
| 
      
 36 
     | 
    
         
            +
                @simulate_hijack && @bus.long_polling_enabled?
         
     | 
| 
       28 
37 
     | 
    
         
             
              end
         
     | 
| 
       29 
38 
     | 
    
         | 
| 
       30 
39 
     | 
    
         
             
              def call(env)
         
     | 
| 
       31 
     | 
    
         
            -
                if simulate_thin_async
         
     | 
| 
      
 40 
     | 
    
         
            +
                if simulate_thin_async?
         
     | 
| 
       32 
41 
     | 
    
         
             
                  call_thin_async(env)
         
     | 
| 
       33 
     | 
    
         
            -
                elsif simulate_hijack
         
     | 
| 
      
 42 
     | 
    
         
            +
                elsif simulate_hijack?
         
     | 
| 
       34 
43 
     | 
    
         
             
                  call_rack_hijack(env)
         
     | 
| 
       35 
     | 
    
         
            -
                else 
     | 
| 
      
 44 
     | 
    
         
            +
                else
         
     | 
| 
       36 
45 
     | 
    
         
             
                  @app.call(env)
         
     | 
| 
       37 
46 
     | 
    
         
             
                end
         
     | 
| 
       38 
47 
     | 
    
         
             
              end
         
     | 
| 
         @@ -64,12 +73,12 @@ class FakeAsyncMiddleware 
     | 
|
| 
       64 
73 
     | 
    
         
             
                  env['rack.hijack_io'] = io
         
     | 
| 
       65 
74 
     | 
    
         | 
| 
       66 
75 
     | 
    
         
             
                  result = @app.call(env)
         
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
       68 
77 
     | 
    
         
             
                  EM::Timer.new(1) { EM.stop }
         
     | 
| 
       69 
78 
     | 
    
         | 
| 
       70 
79 
     | 
    
         
             
                  defer = lambda {
         
     | 
| 
       71 
80 
     | 
    
         
             
                    if !io || !io.closed?
         
     | 
| 
       72 
     | 
    
         
            -
                       
     | 
| 
      
 81 
     | 
    
         
            +
                      @in_async = true
         
     | 
| 
       73 
82 
     | 
    
         
             
                      EM.next_tick do
         
     | 
| 
       74 
83 
     | 
    
         
             
                        defer.call
         
     | 
| 
       75 
84 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -88,7 +97,7 @@ class FakeAsyncMiddleware 
     | 
|
| 
       88 
97 
     | 
    
         
             
                  end
         
     | 
| 
       89 
98 
     | 
    
         
             
                }
         
     | 
| 
       90 
99 
     | 
    
         | 
| 
       91 
     | 
    
         
            -
                 
     | 
| 
      
 100 
     | 
    
         
            +
                @in_async = false
         
     | 
| 
       92 
101 
     | 
    
         
             
                result || [500, {}, ['timeout']]
         
     | 
| 
       93 
102 
     | 
    
         | 
| 
       94 
103 
     | 
    
         
             
              end
         
     | 
| 
         @@ -116,7 +125,7 @@ class FakeAsyncMiddleware 
     | 
|
| 
       116 
125 
     | 
    
         | 
| 
       117 
126 
     | 
    
         
             
                  defer = lambda {
         
     | 
| 
       118 
127 
     | 
    
         
             
                    if !result
         
     | 
| 
       119 
     | 
    
         
            -
                       
     | 
| 
      
 128 
     | 
    
         
            +
                      @in_async = true
         
     | 
| 
       120 
129 
     | 
    
         
             
                      EM.next_tick do
         
     | 
| 
       121 
130 
     | 
    
         
             
                        defer.call
         
     | 
| 
       122 
131 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -127,7 +136,7 @@ class FakeAsyncMiddleware 
     | 
|
| 
       127 
136 
     | 
    
         
             
                  defer.call
         
     | 
| 
       128 
137 
     | 
    
         
             
                }
         
     | 
| 
       129 
138 
     | 
    
         | 
| 
       130 
     | 
    
         
            -
                 
     | 
| 
      
 139 
     | 
    
         
            +
                @in_async = false
         
     | 
| 
       131 
140 
     | 
    
         
             
                result || [500, {}, ['timeout']]
         
     | 
| 
       132 
141 
     | 
    
         
             
              end
         
     | 
| 
       133 
142 
     | 
    
         
             
            end
         
     | 
| 
         @@ -14,6 +14,7 @@ describe MessageBus do 
     | 
|
| 
       14 
14 
     | 
    
         
             
              end
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
       16 
16 
     | 
    
         
             
              after do
         
     | 
| 
      
 17 
     | 
    
         
            +
                @bus.reset!
         
     | 
| 
       17 
18 
     | 
    
         
             
                @bus.destroy
         
     | 
| 
       18 
19 
     | 
    
         
             
              end
         
     | 
| 
       19 
20 
     | 
    
         | 
| 
         @@ -79,6 +80,65 @@ describe MessageBus do 
     | 
|
| 
       79 
80 
     | 
    
         
             
                r.map{|i| i.data}.to_a.should == ['foo', 'bar']
         
     | 
| 
       80 
81 
     | 
    
         
             
              end
         
     | 
| 
       81 
82 
     | 
    
         | 
| 
      
 83 
     | 
    
         
            +
              it "allows you to look up last_message" do
         
     | 
| 
      
 84 
     | 
    
         
            +
                @bus.publish("/bob", "dylan")
         
     | 
| 
      
 85 
     | 
    
         
            +
                @bus.publish("/bob", "marley")
         
     | 
| 
      
 86 
     | 
    
         
            +
                @bus.last_message("/bob").data.should == "marley"
         
     | 
| 
      
 87 
     | 
    
         
            +
                @bus.last_message("/nothing").should == nil
         
     | 
| 
      
 88 
     | 
    
         
            +
              end
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
              context "global subscriptions" do
         
     | 
| 
      
 91 
     | 
    
         
            +
                before do
         
     | 
| 
      
 92 
     | 
    
         
            +
                  seq = 0
         
     | 
| 
      
 93 
     | 
    
         
            +
                  @bus.site_id_lookup do
         
     | 
| 
      
 94 
     | 
    
         
            +
                    (seq+=1).to_s
         
     | 
| 
      
 95 
     | 
    
         
            +
                  end
         
     | 
| 
      
 96 
     | 
    
         
            +
                end
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                it "can get last_message" do
         
     | 
| 
      
 99 
     | 
    
         
            +
                  @bus.publish("/global/test", "test")
         
     | 
| 
      
 100 
     | 
    
         
            +
                  @bus.last_message("/global/test").data.should == "test"
         
     | 
| 
      
 101 
     | 
    
         
            +
                end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                it "can subscribe globally" do
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                  data = nil
         
     | 
| 
      
 106 
     | 
    
         
            +
                  @bus.subscribe do |message|
         
     | 
| 
      
 107 
     | 
    
         
            +
                    data = message.data
         
     | 
| 
      
 108 
     | 
    
         
            +
                  end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                  @bus.publish("/global/test", "test")
         
     | 
| 
      
 111 
     | 
    
         
            +
                  wait_for(1000){ data }
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                  data.should == "test"
         
     | 
| 
      
 114 
     | 
    
         
            +
                end
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                it "can subscribe to channel" do
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                  data = nil
         
     | 
| 
      
 119 
     | 
    
         
            +
                  @bus.subscribe("/global/test") do |message|
         
     | 
| 
      
 120 
     | 
    
         
            +
                    data = message.data
         
     | 
| 
      
 121 
     | 
    
         
            +
                  end
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                  @bus.publish("/global/test", "test")
         
     | 
| 
      
 124 
     | 
    
         
            +
                  wait_for(1000){ data }
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                  data.should == "test"
         
     | 
| 
      
 127 
     | 
    
         
            +
                end
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                it "should exception if publishing restricted messages to user" do
         
     | 
| 
      
 130 
     | 
    
         
            +
                  lambda do
         
     | 
| 
      
 131 
     | 
    
         
            +
                    @bus.publish("/global/test", "test", user_ids: [1])
         
     | 
| 
      
 132 
     | 
    
         
            +
                  end.should raise_error(MessageBus::InvalidMessage)
         
     | 
| 
      
 133 
     | 
    
         
            +
                end
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                it "should exception if publishing restricted messages to group" do
         
     | 
| 
      
 136 
     | 
    
         
            +
                  lambda do
         
     | 
| 
      
 137 
     | 
    
         
            +
                    @bus.publish("/global/test", "test", user_ids: [1])
         
     | 
| 
      
 138 
     | 
    
         
            +
                  end.should raise_error(MessageBus::InvalidMessage)
         
     | 
| 
      
 139 
     | 
    
         
            +
                end
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
              end
         
     | 
| 
       82 
142 
     | 
    
         | 
| 
       83 
143 
     | 
    
         
             
              it "should support forking properly do" do
         
     | 
| 
       84 
144 
     | 
    
         
             
                data = nil
         
     | 
    
        data/spec/lib/middleware_spec.rb
    CHANGED
    
    | 
         @@ -8,25 +8,37 @@ describe MessageBus::Rack::Middleware do 
     | 
|
| 
       8 
8 
     | 
    
         
             
              include Rack::Test::Methods
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
              before do
         
     | 
| 
       11 
     | 
    
         
            -
                 
     | 
| 
      
 11 
     | 
    
         
            +
                bus = @bus = MessageBus::Instance.new
         
     | 
| 
      
 12 
     | 
    
         
            +
                @bus.long_polling_enabled = false
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                builder = Rack::Builder.new {
         
     | 
| 
      
 15 
     | 
    
         
            +
                  use FakeAsyncMiddleware, :message_bus => bus
         
     | 
| 
      
 16 
     | 
    
         
            +
                  use MessageBus::Rack::Middleware, :message_bus => bus
         
     | 
| 
      
 17 
     | 
    
         
            +
                  run lambda {|env| [500, {'Content-Type' => 'text/html'}, 'should not be called' ]}
         
     | 
| 
      
 18 
     | 
    
         
            +
                }
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                @async_middleware = builder.to_app
         
     | 
| 
      
 21 
     | 
    
         
            +
                @message_bus_middleware = @async_middleware.app
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              after do |x|
         
     | 
| 
      
 25 
     | 
    
         
            +
                @message_bus_middleware.stop_listener
         
     | 
| 
      
 26 
     | 
    
         
            +
                @bus.reset!
         
     | 
| 
      
 27 
     | 
    
         
            +
                @bus.destroy
         
     | 
| 
       12 
28 
     | 
    
         
             
              end
         
     | 
| 
       13 
29 
     | 
    
         | 
| 
       14 
30 
     | 
    
         
             
              def app
         
     | 
| 
       15 
     | 
    
         
            -
                @ 
     | 
| 
       16 
     | 
    
         
            -
                  use FakeAsyncMiddleware
         
     | 
| 
       17 
     | 
    
         
            -
                  use MessageBus::Rack::Middleware
         
     | 
| 
       18 
     | 
    
         
            -
                  run lambda {|env| [500, {'Content-Type' => 'text/html'}, 'should not be called' ]}
         
     | 
| 
       19 
     | 
    
         
            -
                }.to_app
         
     | 
| 
      
 31 
     | 
    
         
            +
                @async_middleware
         
     | 
| 
       20 
32 
     | 
    
         
             
              end
         
     | 
| 
       21 
33 
     | 
    
         | 
| 
       22 
34 
     | 
    
         
             
              shared_examples "long polling" do
         
     | 
| 
       23 
35 
     | 
    
         
             
                before do
         
     | 
| 
       24 
     | 
    
         
            -
                   
     | 
| 
      
 36 
     | 
    
         
            +
                  @bus.long_polling_enabled = true
         
     | 
| 
       25 
37 
     | 
    
         
             
                end
         
     | 
| 
       26 
38 
     | 
    
         | 
| 
       27 
39 
     | 
    
         
             
                it "should respond right away if dlp=t" do
         
     | 
| 
       28 
40 
     | 
    
         
             
                  post "/message-bus/ABC?dlp=t", '/foo1' => 0
         
     | 
| 
       29 
     | 
    
         
            -
                   
     | 
| 
      
 41 
     | 
    
         
            +
                  @async_middleware.in_async?.should == false
         
     | 
| 
       30 
42 
     | 
    
         
             
                  last_response.should be_ok
         
     | 
| 
       31 
43 
     | 
    
         
             
                end
         
     | 
| 
       32 
44 
     | 
    
         | 
| 
         @@ -36,14 +48,16 @@ describe MessageBus::Rack::Middleware do 
     | 
|
| 
       36 
48 
     | 
    
         
             
                  parsed = JSON.parse(last_response.body)
         
     | 
| 
       37 
49 
     | 
    
         
             
                  parsed.length.should == 1
         
     | 
| 
       38 
50 
     | 
    
         
             
                  parsed[0]["channel"].should == "/__status"
         
     | 
| 
       39 
     | 
    
         
            -
                  parsed[0]["data"]["/foo"].should ==  
     | 
| 
      
 51 
     | 
    
         
            +
                  parsed[0]["data"]["/foo"].should == @bus.last_id("/foo")
         
     | 
| 
       40 
52 
     | 
    
         
             
                end
         
     | 
| 
       41 
53 
     | 
    
         | 
| 
       42 
54 
     | 
    
         
             
                it "should respond to long polls when data is available" do
         
     | 
| 
      
 55 
     | 
    
         
            +
                  middleware = @async_middleware
         
     | 
| 
      
 56 
     | 
    
         
            +
                  bus = @bus
         
     | 
| 
       43 
57 
     | 
    
         | 
| 
       44 
58 
     | 
    
         
             
                  Thread.new do
         
     | 
| 
       45 
     | 
    
         
            -
                    wait_for(2000) { 
     | 
| 
       46 
     | 
    
         
            -
                     
     | 
| 
      
 59 
     | 
    
         
            +
                    wait_for(2000) {middleware.in_async?}
         
     | 
| 
      
 60 
     | 
    
         
            +
                    bus.publish "/foo", "םוֹלשָׁ"
         
     | 
| 
       47 
61 
     | 
    
         
             
                  end
         
     | 
| 
       48 
62 
     | 
    
         | 
| 
       49 
63 
     | 
    
         
             
                  post "/message-bus/ABC", '/foo' => nil
         
     | 
| 
         @@ -56,21 +70,24 @@ describe MessageBus::Rack::Middleware do 
     | 
|
| 
       56 
70 
     | 
    
         | 
| 
       57 
71 
     | 
    
         
             
                it "should timeout within its alloted slot" do
         
     | 
| 
       58 
72 
     | 
    
         
             
                  begin
         
     | 
| 
       59 
     | 
    
         
            -
                     
     | 
| 
      
 73 
     | 
    
         
            +
                    @bus.long_polling_interval = 10
         
     | 
| 
       60 
74 
     | 
    
         
             
                    s = Time.now.to_f * 1000
         
     | 
| 
       61 
75 
     | 
    
         
             
                    post "/message-bus/ABC", '/foo' => nil
         
     | 
| 
       62 
76 
     | 
    
         
             
                    (Time.now.to_f * 1000 - s).should < 30
         
     | 
| 
       63 
77 
     | 
    
         
             
                  ensure
         
     | 
| 
       64 
     | 
    
         
            -
                     
     | 
| 
      
 78 
     | 
    
         
            +
                    @bus.long_polling_interval = 5000
         
     | 
| 
       65 
79 
     | 
    
         
             
                  end
         
     | 
| 
       66 
80 
     | 
    
         
             
                end
         
     | 
| 
       67 
81 
     | 
    
         | 
| 
       68 
82 
     | 
    
         
             
                it "should support batch filtering" do
         
     | 
| 
       69 
     | 
    
         
            -
                   
     | 
| 
      
 83 
     | 
    
         
            +
                  bus = @bus
         
     | 
| 
      
 84 
     | 
    
         
            +
                  async_middleware = @async_middleware
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                  bus.user_id_lookup do |env|
         
     | 
| 
       70 
87 
     | 
    
         
             
                    1
         
     | 
| 
       71 
88 
     | 
    
         
             
                  end
         
     | 
| 
       72 
89 
     | 
    
         | 
| 
       73 
     | 
    
         
            -
                   
     | 
| 
      
 90 
     | 
    
         
            +
                  bus.around_client_batch("/demo") do |message, user_ids, callback|
         
     | 
| 
       74 
91 
     | 
    
         
             
                    begin
         
     | 
| 
       75 
92 
     | 
    
         
             
                      Thread.current["test"] = user_ids
         
     | 
| 
       76 
93 
     | 
    
         
             
                      callback.call
         
     | 
| 
         @@ -81,18 +98,18 @@ describe MessageBus::Rack::Middleware do 
     | 
|
| 
       81 
98 
     | 
    
         | 
| 
       82 
99 
     | 
    
         
             
                  test = nil
         
     | 
| 
       83 
100 
     | 
    
         | 
| 
       84 
     | 
    
         
            -
                   
     | 
| 
      
 101 
     | 
    
         
            +
                  bus.client_filter("/demo") do |user_id, message|
         
     | 
| 
       85 
102 
     | 
    
         
             
                    test = Thread.current["test"]
         
     | 
| 
       86 
103 
     | 
    
         
             
                    message
         
     | 
| 
       87 
104 
     | 
    
         
             
                  end
         
     | 
| 
       88 
105 
     | 
    
         | 
| 
       89 
106 
     | 
    
         
             
                  client_id = "ABCD"
         
     | 
| 
       90 
107 
     | 
    
         | 
| 
       91 
     | 
    
         
            -
                  id =  
     | 
| 
      
 108 
     | 
    
         
            +
                  id = bus.publish("/demo", "test")
         
     | 
| 
       92 
109 
     | 
    
         | 
| 
       93 
110 
     | 
    
         
             
                  Thread.new do
         
     | 
| 
       94 
     | 
    
         
            -
                    wait_for(2000) {  
     | 
| 
       95 
     | 
    
         
            -
                     
     | 
| 
      
 111 
     | 
    
         
            +
                    wait_for(2000) { async_middleware.in_async? }
         
     | 
| 
      
 112 
     | 
    
         
            +
                    bus.publish "/demo", "test"
         
     | 
| 
       96 
113 
     | 
    
         
             
                  end
         
     | 
| 
       97 
114 
     | 
    
         | 
| 
       98 
115 
     | 
    
         
             
                  post "/message-bus/#{client_id}", {
         
     | 
| 
         @@ -105,15 +122,15 @@ describe MessageBus::Rack::Middleware do 
     | 
|
| 
       105 
122 
     | 
    
         | 
| 
       106 
123 
     | 
    
         
             
              describe "thin async" do
         
     | 
| 
       107 
124 
     | 
    
         
             
                before do
         
     | 
| 
       108 
     | 
    
         
            -
                   
     | 
| 
      
 125 
     | 
    
         
            +
                  @async_middleware.simulate_thin_async
         
     | 
| 
       109 
126 
     | 
    
         
             
                end
         
     | 
| 
       110 
127 
     | 
    
         
             
                it_behaves_like "long polling"
         
     | 
| 
       111 
128 
     | 
    
         
             
              end
         
     | 
| 
       112 
129 
     | 
    
         | 
| 
       113 
130 
     | 
    
         
             
              describe "hijack" do
         
     | 
| 
       114 
131 
     | 
    
         
             
                before do
         
     | 
| 
       115 
     | 
    
         
            -
                   
     | 
| 
       116 
     | 
    
         
            -
                   
     | 
| 
      
 132 
     | 
    
         
            +
                  @async_middleware.simulate_hijack
         
     | 
| 
      
 133 
     | 
    
         
            +
                  @bus.rack_hijack_enabled = true
         
     | 
| 
       117 
134 
     | 
    
         
             
                end
         
     | 
| 
       118 
135 
     | 
    
         
             
                it_behaves_like "long polling"
         
     | 
| 
       119 
136 
     | 
    
         
             
              end
         
     | 
| 
         @@ -126,13 +143,13 @@ describe MessageBus::Rack::Middleware do 
     | 
|
| 
       126 
143 
     | 
    
         
             
                end
         
     | 
| 
       127 
144 
     | 
    
         | 
| 
       128 
145 
     | 
    
         
             
                it "should get a 200 with html for an authorized user" do
         
     | 
| 
       129 
     | 
    
         
            -
                   
     | 
| 
      
 146 
     | 
    
         
            +
                  @bus.stub(:is_admin_lookup).and_return(lambda{|env| true })
         
     | 
| 
       130 
147 
     | 
    
         
             
                  get "/message-bus/_diagnostics"
         
     | 
| 
       131 
148 
     | 
    
         
             
                  last_response.status.should == 200
         
     | 
| 
       132 
149 
     | 
    
         
             
                end
         
     | 
| 
       133 
150 
     | 
    
         | 
| 
       134 
151 
     | 
    
         
             
                it "should get the script it asks for" do
         
     | 
| 
       135 
     | 
    
         
            -
                   
     | 
| 
      
 152 
     | 
    
         
            +
                  @bus.stub(:is_admin_lookup).and_return(lambda{|env| true })
         
     | 
| 
       136 
153 
     | 
    
         
             
                  get "/message-bus/_diagnostics/assets/message-bus.js"
         
     | 
| 
       137 
154 
     | 
    
         
             
                  last_response.status.should == 200
         
     | 
| 
       138 
155 
     | 
    
         
             
                  last_response.content_type.should == "text/javascript;"
         
     | 
| 
         @@ -142,7 +159,7 @@ describe MessageBus::Rack::Middleware do 
     | 
|
| 
       142 
159 
     | 
    
         | 
| 
       143 
160 
     | 
    
         
             
              describe "polling" do
         
     | 
| 
       144 
161 
     | 
    
         
             
                before do
         
     | 
| 
       145 
     | 
    
         
            -
                   
     | 
| 
      
 162 
     | 
    
         
            +
                  @bus.long_polling_enabled = false
         
     | 
| 
       146 
163 
     | 
    
         
             
                end
         
     | 
| 
       147 
164 
     | 
    
         | 
| 
       148 
165 
     | 
    
         
             
                it "should respond with a 200 to a subscribe" do
         
     | 
| 
         @@ -158,7 +175,7 @@ describe MessageBus::Rack::Middleware do 
     | 
|
| 
       158 
175 
     | 
    
         | 
| 
       159 
176 
     | 
    
         
             
                it "should correctly understand that -1 means stuff from now onwards" do
         
     | 
| 
       160 
177 
     | 
    
         | 
| 
       161 
     | 
    
         
            -
                   
     | 
| 
      
 178 
     | 
    
         
            +
                  @bus.publish('foo', 'bar')
         
     | 
| 
       162 
179 
     | 
    
         | 
| 
       163 
180 
     | 
    
         
             
                  post "/message-bus/ABCD", {
         
     | 
| 
       164 
181 
     | 
    
         
             
                    '/foo' => -1
         
     | 
| 
         @@ -167,15 +184,15 @@ describe MessageBus::Rack::Middleware do 
     | 
|
| 
       167 
184 
     | 
    
         
             
                  parsed = JSON.parse(last_response.body)
         
     | 
| 
       168 
185 
     | 
    
         
             
                  parsed.length.should == 1
         
     | 
| 
       169 
186 
     | 
    
         
             
                  parsed[0]["channel"].should == "/__status"
         
     | 
| 
       170 
     | 
    
         
            -
                  parsed[0]["data"]["/foo"].should  
     | 
| 
      
 187 
     | 
    
         
            +
                  parsed[0]["data"]["/foo"].should ==@bus.last_id("/foo")
         
     | 
| 
       171 
188 
     | 
    
         | 
| 
       172 
189 
     | 
    
         
             
                end
         
     | 
| 
       173 
190 
     | 
    
         | 
| 
       174 
191 
     | 
    
         
             
                it "should respond with the data if messages exist in the backlog" do
         
     | 
| 
       175 
     | 
    
         
            -
                  id  
     | 
| 
      
 192 
     | 
    
         
            +
                  id =@bus.last_id('/foo')
         
     | 
| 
       176 
193 
     | 
    
         | 
| 
       177 
     | 
    
         
            -
                   
     | 
| 
       178 
     | 
    
         
            -
                   
     | 
| 
      
 194 
     | 
    
         
            +
                  @bus.publish("/foo", "barbs")
         
     | 
| 
      
 195 
     | 
    
         
            +
                  @bus.publish("/foo", "borbs")
         
     | 
| 
       179 
196 
     | 
    
         | 
| 
       180 
197 
     | 
    
         
             
                  client_id = "ABCD"
         
     | 
| 
       181 
198 
     | 
    
         
             
                  post "/message-bus/#{client_id}", {
         
     | 
| 
         @@ -189,9 +206,46 @@ describe MessageBus::Rack::Middleware do 
     | 
|
| 
       189 
206 
     | 
    
         
             
                  parsed[1]["data"].should == "borbs"
         
     | 
| 
       190 
207 
     | 
    
         
             
                end
         
     | 
| 
       191 
208 
     | 
    
         | 
| 
      
 209 
     | 
    
         
            +
                it "should have no cross talk" do
         
     | 
| 
      
 210 
     | 
    
         
            +
             
     | 
| 
      
 211 
     | 
    
         
            +
                  seq = 0
         
     | 
| 
      
 212 
     | 
    
         
            +
                  @bus.site_id_lookup do
         
     | 
| 
      
 213 
     | 
    
         
            +
                    (seq+=1).to_s
         
     | 
| 
      
 214 
     | 
    
         
            +
                  end
         
     | 
| 
      
 215 
     | 
    
         
            +
             
     | 
| 
      
 216 
     | 
    
         
            +
                  # published on channel 1
         
     | 
| 
      
 217 
     | 
    
         
            +
                  msg = @bus.publish("/foo", "test")
         
     | 
| 
      
 218 
     | 
    
         
            +
             
     | 
| 
      
 219 
     | 
    
         
            +
                  # subscribed on channel 2
         
     | 
| 
      
 220 
     | 
    
         
            +
                  post "/message-bus/ABCD", {
         
     | 
| 
      
 221 
     | 
    
         
            +
                    '/foo' => (msg-1)
         
     | 
| 
      
 222 
     | 
    
         
            +
                  }
         
     | 
| 
      
 223 
     | 
    
         
            +
             
     | 
| 
      
 224 
     | 
    
         
            +
                  parsed = JSON.parse(last_response.body)
         
     | 
| 
      
 225 
     | 
    
         
            +
                  parsed.length.should == 0
         
     | 
| 
      
 226 
     | 
    
         
            +
             
     | 
| 
      
 227 
     | 
    
         
            +
                end
         
     | 
| 
      
 228 
     | 
    
         
            +
             
     | 
| 
      
 229 
     | 
    
         
            +
                it "should have global cross talk" do
         
     | 
| 
      
 230 
     | 
    
         
            +
             
     | 
| 
      
 231 
     | 
    
         
            +
                  seq = 0
         
     | 
| 
      
 232 
     | 
    
         
            +
                  @bus.site_id_lookup do
         
     | 
| 
      
 233 
     | 
    
         
            +
                    (seq+=1).to_s
         
     | 
| 
      
 234 
     | 
    
         
            +
                  end
         
     | 
| 
      
 235 
     | 
    
         
            +
             
     | 
| 
      
 236 
     | 
    
         
            +
                  msg = @bus.publish("/global/foo", "test")
         
     | 
| 
      
 237 
     | 
    
         
            +
             
     | 
| 
      
 238 
     | 
    
         
            +
                  post "/message-bus/ABCD", {
         
     | 
| 
      
 239 
     | 
    
         
            +
                    '/global/foo' => (msg-1)
         
     | 
| 
      
 240 
     | 
    
         
            +
                  }
         
     | 
| 
      
 241 
     | 
    
         
            +
             
     | 
| 
      
 242 
     | 
    
         
            +
                  parsed = JSON.parse(last_response.body)
         
     | 
| 
      
 243 
     | 
    
         
            +
                  parsed.length.should == 1
         
     | 
| 
      
 244 
     | 
    
         
            +
                end
         
     | 
| 
      
 245 
     | 
    
         
            +
             
     | 
| 
       192 
246 
     | 
    
         
             
                it "should not get consumed messages" do
         
     | 
| 
       193 
     | 
    
         
            -
                   
     | 
| 
       194 
     | 
    
         
            -
                  id  
     | 
| 
      
 247 
     | 
    
         
            +
                  @bus.publish("/foo", "barbs")
         
     | 
| 
      
 248 
     | 
    
         
            +
                  id =@bus.last_id('/foo')
         
     | 
| 
       195 
249 
     | 
    
         | 
| 
       196 
250 
     | 
    
         
             
                  client_id = "ABCD"
         
     | 
| 
       197 
251 
     | 
    
         
             
                  post "/message-bus/#{client_id}", {
         
     | 
| 
         @@ -203,8 +257,8 @@ describe MessageBus::Rack::Middleware do 
     | 
|
| 
       203 
257 
     | 
    
         
             
                end
         
     | 
| 
       204 
258 
     | 
    
         | 
| 
       205 
259 
     | 
    
         
             
                it "should filter by user correctly" do
         
     | 
| 
       206 
     | 
    
         
            -
                  id  
     | 
| 
       207 
     | 
    
         
            -
                   
     | 
| 
      
 260 
     | 
    
         
            +
                  id =@bus.publish("/foo", "test", user_ids: [1])
         
     | 
| 
      
 261 
     | 
    
         
            +
                  @bus.user_id_lookup do |env|
         
     | 
| 
       208 
262 
     | 
    
         
             
                    0
         
     | 
| 
       209 
263 
     | 
    
         
             
                  end
         
     | 
| 
       210 
264 
     | 
    
         | 
| 
         @@ -216,7 +270,7 @@ describe MessageBus::Rack::Middleware do 
     | 
|
| 
       216 
270 
     | 
    
         
             
                  parsed = JSON.parse(last_response.body)
         
     | 
| 
       217 
271 
     | 
    
         
             
                  parsed.length.should == 0
         
     | 
| 
       218 
272 
     | 
    
         | 
| 
       219 
     | 
    
         
            -
                   
     | 
| 
      
 273 
     | 
    
         
            +
                  @bus.user_id_lookup do |env|
         
     | 
| 
       220 
274 
     | 
    
         
             
                    1
         
     | 
| 
       221 
275 
     | 
    
         
             
                  end
         
     | 
| 
       222 
276 
     | 
    
         | 
| 
         @@ -230,14 +284,14 @@ describe MessageBus::Rack::Middleware do 
     | 
|
| 
       230 
284 
     | 
    
         | 
| 
       231 
285 
     | 
    
         | 
| 
       232 
286 
     | 
    
         
             
                it "should filter by client_filter correctly" do
         
     | 
| 
       233 
     | 
    
         
            -
                  id =  
     | 
| 
       234 
     | 
    
         
            -
                   
     | 
| 
      
 287 
     | 
    
         
            +
                  id = @bus.publish("/filter", "test")
         
     | 
| 
      
 288 
     | 
    
         
            +
                  uid = 0
         
     | 
| 
       235 
289 
     | 
    
         | 
| 
       236 
     | 
    
         
            -
                   
     | 
| 
       237 
     | 
    
         
            -
                     
     | 
| 
      
 290 
     | 
    
         
            +
                  @bus.user_id_lookup do |env|
         
     | 
| 
      
 291 
     | 
    
         
            +
                    uid
         
     | 
| 
       238 
292 
     | 
    
         
             
                  end
         
     | 
| 
       239 
293 
     | 
    
         | 
| 
       240 
     | 
    
         
            -
                   
     | 
| 
      
 294 
     | 
    
         
            +
                  @bus.client_filter("/filter") do |user_id, message|
         
     | 
| 
       241 
295 
     | 
    
         
             
                    if user_id == 0
         
     | 
| 
       242 
296 
     | 
    
         
             
                      message = message.dup
         
     | 
| 
       243 
297 
     | 
    
         
             
                      message.data += "_filter"
         
     | 
| 
         @@ -256,7 +310,7 @@ describe MessageBus::Rack::Middleware do 
     | 
|
| 
       256 
310 
     | 
    
         
             
                  parsed = JSON.parse(last_response.body)
         
     | 
| 
       257 
311 
     | 
    
         
             
                  parsed[0]['data'].should == "test_filter"
         
     | 
| 
       258 
312 
     | 
    
         | 
| 
       259 
     | 
    
         
            -
                   
     | 
| 
      
 313 
     | 
    
         
            +
                  uid = 1
         
     | 
| 
       260 
314 
     | 
    
         | 
| 
       261 
315 
     | 
    
         
             
                  post "/message-bus/#{client_id}", {
         
     | 
| 
       262 
316 
     | 
    
         
             
                    '/filter' => id - 1
         
     | 
| 
         @@ -266,7 +320,7 @@ describe MessageBus::Rack::Middleware do 
     | 
|
| 
       266 
320 
     | 
    
         
             
                  parsed.length.should == 1
         
     | 
| 
       267 
321 
     | 
    
         
             
                  parsed[0]["data"].should == "test"
         
     | 
| 
       268 
322 
     | 
    
         | 
| 
       269 
     | 
    
         
            -
                   
     | 
| 
      
 323 
     | 
    
         
            +
                  uid = 2
         
     | 
| 
       270 
324 
     | 
    
         | 
| 
       271 
325 
     | 
    
         
             
                  post "/message-bus/#{client_id}", {
         
     | 
| 
       272 
326 
     | 
    
         
             
                    '/filter' => id - 1
         
     | 
| 
         @@ -277,8 +331,8 @@ describe MessageBus::Rack::Middleware do 
     | 
|
| 
       277 
331 
     | 
    
         
             
                end
         
     | 
| 
       278 
332 
     | 
    
         | 
| 
       279 
333 
     | 
    
         
             
                it "should filter by group correctly" do
         
     | 
| 
       280 
     | 
    
         
            -
                  id  
     | 
| 
       281 
     | 
    
         
            -
                   
     | 
| 
      
 334 
     | 
    
         
            +
                  id =@bus.publish("/foo", "test", group_ids: [3,4,5])
         
     | 
| 
      
 335 
     | 
    
         
            +
                  @bus.group_ids_lookup do |env|
         
     | 
| 
       282 
336 
     | 
    
         
             
                    [0,1,2]
         
     | 
| 
       283 
337 
     | 
    
         
             
                  end
         
     | 
| 
       284 
338 
     | 
    
         | 
| 
         @@ -290,7 +344,7 @@ describe MessageBus::Rack::Middleware do 
     | 
|
| 
       290 
344 
     | 
    
         
             
                  parsed = JSON.parse(last_response.body)
         
     | 
| 
       291 
345 
     | 
    
         
             
                  parsed.length.should == 0
         
     | 
| 
       292 
346 
     | 
    
         | 
| 
       293 
     | 
    
         
            -
                   
     | 
| 
      
 347 
     | 
    
         
            +
                  @bus.group_ids_lookup do |env|
         
     | 
| 
       294 
348 
     | 
    
         
             
                    [1,7,4,100]
         
     | 
| 
       295 
349 
     | 
    
         
             
                  end
         
     | 
| 
       296 
350 
     | 
    
         | 
| 
         @@ -119,6 +119,7 @@ window.MessageBus = (function() { 
     | 
|
| 
       119 
119 
     | 
    
         
             
                  },
         
     | 
| 
       120 
120 
     | 
    
         
             
                  success: function(messages) {
         
     | 
| 
       121 
121 
     | 
    
         
             
                    failCount = 0;
         
     | 
| 
      
 122 
     | 
    
         
            +
                    if (messages === null) return; // server unexpectedly closed connection
         
     | 
| 
       122 
123 
     | 
    
         
             
                    $.each(messages,function(_,message) {
         
     | 
| 
       123 
124 
     | 
    
         
             
                      gotData = true;
         
     | 
| 
       124 
125 
     | 
    
         
             
                      $.each(callbacks, function(_,callback) {
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: message_bus
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.9. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.9.4
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Sam Saffron
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date:  
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2014-01-14 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: rack
         
     | 
| 
         @@ -80,6 +80,8 @@ files: 
     | 
|
| 
       80 
80 
     | 
    
         
             
            - examples/bench/unicorn.conf.rb
         
     | 
| 
       81 
81 
     | 
    
         
             
            - examples/chat/chat.rb
         
     | 
| 
       82 
82 
     | 
    
         
             
            - examples/chat/config.ru
         
     | 
| 
      
 83 
     | 
    
         
            +
            - examples/minimal/Gemfile
         
     | 
| 
      
 84 
     | 
    
         
            +
            - examples/minimal/config.ru
         
     | 
| 
       83 
85 
     | 
    
         
             
            - lib/message_bus.rb
         
     | 
| 
       84 
86 
     | 
    
         
             
            - lib/message_bus/client.rb
         
     | 
| 
       85 
87 
     | 
    
         
             
            - lib/message_bus/connection_manager.rb
         
     |