rasti-web-broadcaster 1.1.0 → 2.0.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 37e3d3a5ed540645ccb1caa500aa4cebc9a73a8b
4
- data.tar.gz: 4a4bde06cbb297ee73e8eaca452a6c9986b7f06a
2
+ SHA256:
3
+ metadata.gz: bee6440950bad244f76deef7e4685575da162bc540699b69b638e78c3eefd131
4
+ data.tar.gz: e84320050ffb17592a5b58f2957a1f1e75727a0200916a8beadd5795a0840ebe
5
5
  SHA512:
6
- metadata.gz: 25ac0b9e1fd65ddd53e5b358e70ec98afd2a8e7595e70f8ed18255e5f81272c586155a7d11af3f5e811af22f1ccd0910e8c02704bba11f8bcea4fb2c0d087dcd
7
- data.tar.gz: 1f918bb57a4e5ade46fa0dd6bc37ccec7bb64f79227387df1c24f0ad32139b86ffd9182946ae47a1bdcfac824ba7a5e8b9932d3fb427be49417acac27666f458
6
+ metadata.gz: 4f4b557db3d69f416a6e89a6ba665a6c18c1b9ba1da9332861fac73eb14cc2acfde9336a4d4013a6a0208bb4688dbc3b9f5c59fbad0d6510dd16848df68b7d0f
7
+ data.tar.gz: d4e9d49f0e703e1087bb5fe3d2d9cfc4369ca8ca123af6f0e4b48e6d02d851c8782b5871bbcdd4ed5b37cb1edd3b998e19bb765a9a31d85527bbfa3194fe25b1
data/.travis.yml CHANGED
@@ -1,14 +1,15 @@
1
1
  language: ruby
2
2
 
3
3
  rvm:
4
- - 1.9.3
5
- - 2.0
6
4
  - 2.1
7
5
  - 2.2
8
- - 2.3.0
9
- - 2.4.0
10
- - jruby-1.7.25
11
- - jruby-9.1.7.0
6
+ - 2.3
7
+ - 2.4
8
+ - 2.5
9
+ - 2.6
10
+ - 2.7
11
+ - 3.0
12
+ - jruby-9.2.9.0
12
13
  - ruby-head
13
14
  - jruby-head
14
15
 
@@ -18,8 +19,5 @@ matrix:
18
19
  - rvm: ruby-head
19
20
  - rvm: jruby-head
20
21
 
21
- before_install:
22
- - gem install bundler
23
-
24
22
  services:
25
23
  - redis-server
data/README.md CHANGED
@@ -1,10 +1,9 @@
1
1
  # Rasti::Web::Broadcaster
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/rasti-web-broadcaster.svg)](https://rubygems.org/gems/rasti-web-broadcaster)
4
- [![Build Status](https://travis-ci.org/gabynaiman/rasti-web-broadcaster.svg?branch=master)](https://travis-ci.org/gabynaiman/rasti-web-broadcaster)
4
+ [![Build Status](https://app.travis-ci.com/gabynaiman/rasti-web-broadcaster.svg?branch=master)](https://app.travis-ci.com/gabynaiman/rasti-web-broadcaster)
5
5
  [![Coverage Status](https://coveralls.io/repos/gabynaiman/rasti-web-broadcaster/badge.svg?branch=master)](https://coveralls.io/r/gabynaiman/rasti-web-broadcaster?branch=master)
6
6
  [![Code Climate](https://codeclimate.com/github/gabynaiman/rasti-web-broadcaster.svg)](https://codeclimate.com/github/gabynaiman/rasti-web-broadcaster)
7
- [![Dependency Status](https://gemnasium.com/gabynaiman/rasti-web-broadcaster.svg)](https://gemnasium.com/gabynaiman/rasti-web-broadcaster)
8
7
 
9
8
  Enable server sent events with rack middleware implemented over Faye and Broadcaster (Redis Pub/Sub)
10
9
 
@@ -31,6 +30,7 @@ Or install it yourself as:
31
30
  Rasti::Web::Broadcaster.configure do |config|
32
31
  config.id = 'AppName'
33
32
  config.redis_settings = "redis://#{ENV['REDIS_HOST']}:#{ENV['REDIS_PORT']}"
33
+ config.keep_alive_interval = 30
34
34
  config.logger = Logger.new "/log/#{ENV['RACK_ENV']}.log"
35
35
  end
36
36
  ```
@@ -0,0 +1,7 @@
1
+ if defined?(Rack::Lint::HijackWrapper) && !Rack::Lint::HijackWrapper.instance_methods.include?(:to_int)
2
+ class Rack::Lint::HijackWrapper
3
+ def to_int
4
+ @io.to_i
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,37 @@
1
+ module Rasti
2
+ module Web
3
+ class Broadcaster
4
+ class Timer
5
+ class << self
6
+
7
+ def every(interval, &block)
8
+ Thread.new do
9
+ loop do
10
+ execute_using_time_slot(interval, &block)
11
+ end
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def execute_using_time_slot(interval)
18
+ started_at = Time.now
19
+ yield
20
+
21
+ rescue => ex
22
+ Broadcaster.logger.error(self) { ex }
23
+
24
+ ensure
25
+ elapsed_time = Time.now - started_at
26
+ if elapsed_time > interval
27
+ Broadcaster.logger.warn(self) { "Elapsed time #{elapsed_time}s for interval of #{interval}s" }
28
+ else
29
+ sleep interval - elapsed_time
30
+ end
31
+ end
32
+
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1,7 +1,7 @@
1
1
  module Rasti
2
2
  module Web
3
3
  class Broadcaster
4
- VERSION = '1.1.0'
4
+ VERSION = '2.0.0'
5
5
  end
6
6
  end
7
7
  end
@@ -3,18 +3,23 @@ require 'broadcaster'
3
3
  require 'class_config'
4
4
 
5
5
  require_relative 'broadcaster/safe_event_machine'
6
+ require_relative 'broadcaster/safe_rack_lint'
7
+ require_relative 'broadcaster/timer'
6
8
  require_relative 'broadcaster/version'
7
9
 
8
10
  module Rasti
9
11
  module Web
10
12
  class Broadcaster
11
13
 
14
+ KEEP_ALIVE_EVENT = 'keepAlive'
15
+
12
16
  extend ClassConfig
13
17
 
14
- attr_config :id, 'rasti.web.broadcaster'
15
- attr_config :redis_client, Redic
16
- attr_config :redis_settings, 'redis://localhost:6379'
17
- attr_config :logger, Logger.new(STDOUT)
18
+ attr_config :id, 'rasti.web.broadcaster'
19
+ attr_config :redis_client, Redic
20
+ attr_config :redis_settings, 'redis://localhost:6379'
21
+ attr_config :logger, Logger.new(STDOUT)
22
+ attr_config :keep_alive_interval
18
23
 
19
24
  @mutex = Mutex.new
20
25
 
@@ -22,8 +27,8 @@ module Rasti
22
27
 
23
28
  extend Forwardable
24
29
 
25
- def_delegators :broadcaster, :subscribe,
26
- :unsubscribe,
30
+ def_delegators :broadcaster, :subscribe,
31
+ :unsubscribe,
27
32
  :publish
28
33
 
29
34
  private
@@ -39,20 +44,20 @@ module Rasti
39
44
  def initialize(app, headers={})
40
45
  @app = app
41
46
  @headers = headers
47
+ @mutex = Mutex.new
48
+ @subscriptions = {}
49
+
50
+ start_sending_keep_alive_messages
42
51
  end
43
52
 
44
53
  def call(env)
45
54
  if Faye::EventSource.eventsource? env
46
- event_source = Faye::EventSource.new env, headers: @headers
47
- channel = env['PATH_INFO'][1..-1]
55
+ event_source = Faye::EventSource.new env, headers: headers
48
56
 
49
- subscription_id = self.class.subscribe channel do |message|
50
- event_source.send message[:data], event: message[:event],
51
- id: message[:id]
52
- end
57
+ subscription_id = subscribe channel_from(env), event_source
53
58
 
54
59
  event_source.on :close do
55
- self.class.unsubscribe subscription_id
60
+ unsubscribe subscription_id
56
61
  event_source = nil
57
62
  end
58
63
 
@@ -64,7 +69,41 @@ module Rasti
64
69
 
65
70
  private
66
71
 
67
- attr_reader :app
72
+ attr_reader :app, :headers, :mutex, :subscriptions
73
+
74
+ def subscribe(channel, event_source)
75
+ subscription_id = self.class.subscribe channel do |message|
76
+ send_message(event_source, **message)
77
+ end
78
+
79
+ mutex.synchronize { subscriptions[subscription_id] = event_source }
80
+
81
+ subscription_id
82
+ end
83
+
84
+ def unsubscribe(subscription_id)
85
+ self.class.unsubscribe subscription_id
86
+ mutex.synchronize { subscriptions.delete subscription_id }
87
+ end
88
+
89
+ def send_message(event_source, data:, event: nil, id: nil)
90
+ event_source.send data, event: event, id: id
91
+ end
92
+
93
+ def start_sending_keep_alive_messages
94
+ if self.class.keep_alive_interval
95
+ Timer.every self.class.keep_alive_interval do
96
+ subscriptions.each do |subscription_id, event_source|
97
+ self.class.logger.debug(self.class) { "Sending keep alive to #{subscription_id}" }
98
+ send_message event_source, data: '', event: KEEP_ALIVE_EVENT
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ def channel_from(env)
105
+ env['PATH_INFO'][1..-1]
106
+ end
68
107
 
69
108
  end
70
109
  end
@@ -18,13 +18,12 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ['lib']
20
20
 
21
- spec.add_runtime_dependency 'faye-websocket', '~> 0.10'
22
- spec.add_runtime_dependency 'broadcaster', '~> 1.0'
21
+ spec.add_runtime_dependency 'faye-websocket', '~> 0.11'
22
+ spec.add_runtime_dependency 'broadcaster', '~> 1.0', '>= 1.0.2'
23
23
  spec.add_runtime_dependency 'class_config', '~> 0.0'
24
24
 
25
- spec.add_development_dependency 'bundler', '~> 1.12'
26
- spec.add_development_dependency 'rake', '~> 11.0'
27
- spec.add_development_dependency 'minitest', '~> 5.0'
25
+ spec.add_development_dependency 'rake', '~> 12.0'
26
+ spec.add_development_dependency 'minitest', '~> 5.0', '< 5.11'
28
27
  spec.add_development_dependency 'minitest-colorin', '~> 0.1'
29
28
  spec.add_development_dependency 'minitest-line', '~> 0.6'
30
29
  spec.add_development_dependency 'simplecov', '~> 0.12'
@@ -32,13 +31,7 @@ Gem::Specification.new do |spec|
32
31
  spec.add_development_dependency 'pry-nav', '~> 0.2'
33
32
  spec.add_development_dependency 'rack-test', '~> 0.6'
34
33
 
35
- if RUBY_VERSION < '2'
36
- spec.add_development_dependency 'term-ansicolor', '~> 1.3.0'
37
- spec.add_development_dependency 'tins', '~> 1.6.0'
38
- spec.add_development_dependency 'json', '~> 1.8'
39
- end
40
-
41
34
  if RUBY_VERSION < '2.2.2'
42
35
  spec.add_development_dependency 'rack', '< 2'
43
36
  end
44
- end
37
+ end
@@ -46,12 +46,12 @@ describe Rasti::Web::Broadcaster do
46
46
 
47
47
  event_source = nil
48
48
  events = []
49
-
50
- env['async.callback'] = proc do |(status, headers, body)|
49
+
50
+ env['async.callback'] = proc do |(_status, _headers, body)|
51
51
  event_source = body.instance_variable_get(:@socket_object)
52
52
  body.each { |e| events << e }
53
53
  end
54
-
54
+
55
55
  Rasti::Web::Broadcaster.publish 'channel_1', data: 'message 0'
56
56
 
57
57
  app.call env
@@ -60,14 +60,15 @@ describe Rasti::Web::Broadcaster do
60
60
  Rasti::Web::Broadcaster.publish 'channel_2', data: 'message 2'
61
61
  Rasti::Web::Broadcaster.publish 'channel_1', data: 'message 3'
62
62
 
63
- wait_for { events.count == 3 }
63
+ wait_for { events.count == 4 }
64
64
 
65
65
  event_source.close
66
66
 
67
67
  events.must_equal [
68
68
  event_headers,
69
- event_for(data: 'message 1', event: 'event_1', id: 1),
70
- event_for(data: 'message 3')
69
+ event_for(data: 'message 1', event: 'event_1', id: 1),
70
+ event_for(data: 'message 3'),
71
+ event_for(event: Rasti::Web::Broadcaster::KEEP_ALIVE_EVENT)
71
72
  ]
72
73
  end
73
74
 
@@ -5,4 +5,7 @@ require 'pry-nav'
5
5
  require 'rasti-web-broadcaster'
6
6
  require 'rack/test'
7
7
 
8
- Rasti::Web::Broadcaster.logger.level = Logger::ERROR
8
+ Rasti::Web::Broadcaster.configure do |config|
9
+ config.logger = Logger.new '/dev/null'
10
+ config.keep_alive_interval = 0.1
11
+ end
@@ -0,0 +1,48 @@
1
+ require 'minitest_helper'
2
+
3
+ describe Rasti::Web::Broadcaster::Timer do
4
+
5
+ let(:timer) { Rasti::Web::Broadcaster::Timer }
6
+
7
+ it 'Tick' do
8
+ count = 0
9
+
10
+ thread = timer.every(0.02) do
11
+ count += 1
12
+ end
13
+
14
+ sleep 0.07
15
+ thread.exit
16
+
17
+ count.must_equal 4
18
+ end
19
+
20
+ it 'Interval exceded' do
21
+ count = 0
22
+
23
+ thread = timer.every(0.02) do
24
+ sleep 0.04 if count == 1
25
+ count += 1
26
+ end
27
+
28
+ sleep 0.07
29
+ thread.exit
30
+
31
+ count.must_equal 3
32
+ end
33
+
34
+ it 'Error safe' do
35
+ count = 0
36
+
37
+ thread = timer.every(0.02) do
38
+ count += 1
39
+ raise 'Unexpected error' if count == 2
40
+ end
41
+
42
+ sleep 0.05
43
+ thread.exit
44
+
45
+ count.must_equal 3
46
+ end
47
+
48
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rasti-web-broadcaster
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gabriel Naiman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-10-11 00:00:00.000000000 Z
11
+ date: 2022-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faye-websocket
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.10'
19
+ version: '0.11'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.10'
26
+ version: '0.11'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: broadcaster
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -31,6 +31,9 @@ dependencies:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '1.0'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 1.0.2
34
37
  type: :runtime
35
38
  prerelease: false
36
39
  version_requirements: !ruby/object:Gem::Requirement
@@ -38,6 +41,9 @@ dependencies:
38
41
  - - "~>"
39
42
  - !ruby/object:Gem::Version
40
43
  version: '1.0'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 1.0.2
41
47
  - !ruby/object:Gem::Dependency
42
48
  name: class_config
43
49
  requirement: !ruby/object:Gem::Requirement
@@ -52,34 +58,20 @@ dependencies:
52
58
  - - "~>"
53
59
  - !ruby/object:Gem::Version
54
60
  version: '0.0'
55
- - !ruby/object:Gem::Dependency
56
- name: bundler
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '1.12'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '1.12'
69
61
  - !ruby/object:Gem::Dependency
70
62
  name: rake
71
63
  requirement: !ruby/object:Gem::Requirement
72
64
  requirements:
73
65
  - - "~>"
74
66
  - !ruby/object:Gem::Version
75
- version: '11.0'
67
+ version: '12.0'
76
68
  type: :development
77
69
  prerelease: false
78
70
  version_requirements: !ruby/object:Gem::Requirement
79
71
  requirements:
80
72
  - - "~>"
81
73
  - !ruby/object:Gem::Version
82
- version: '11.0'
74
+ version: '12.0'
83
75
  - !ruby/object:Gem::Dependency
84
76
  name: minitest
85
77
  requirement: !ruby/object:Gem::Requirement
@@ -87,6 +79,9 @@ dependencies:
87
79
  - - "~>"
88
80
  - !ruby/object:Gem::Version
89
81
  version: '5.0'
82
+ - - "<"
83
+ - !ruby/object:Gem::Version
84
+ version: '5.11'
90
85
  type: :development
91
86
  prerelease: false
92
87
  version_requirements: !ruby/object:Gem::Requirement
@@ -94,6 +89,9 @@ dependencies:
94
89
  - - "~>"
95
90
  - !ruby/object:Gem::Version
96
91
  version: '5.0'
92
+ - - "<"
93
+ - !ruby/object:Gem::Version
94
+ version: '5.11'
97
95
  - !ruby/object:Gem::Dependency
98
96
  name: minitest-colorin
99
97
  requirement: !ruby/object:Gem::Requirement
@@ -198,11 +196,14 @@ files:
198
196
  - lib/rasti-web-broadcaster.rb
199
197
  - lib/rasti/web/broadcaster.rb
200
198
  - lib/rasti/web/broadcaster/safe_event_machine.rb
199
+ - lib/rasti/web/broadcaster/safe_rack_lint.rb
200
+ - lib/rasti/web/broadcaster/timer.rb
201
201
  - lib/rasti/web/broadcaster/version.rb
202
202
  - rasti-web-broadcaster.gemspec
203
203
  - spec/coverage_helper.rb
204
204
  - spec/middleware_spec.rb
205
205
  - spec/minitest_helper.rb
206
+ - spec/timer_spec.rb
206
207
  homepage: https://github.com/gabynaiman/rasti-web-broadcaster
207
208
  licenses:
208
209
  - MIT
@@ -222,8 +223,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
222
223
  - !ruby/object:Gem::Version
223
224
  version: '0'
224
225
  requirements: []
225
- rubyforge_project:
226
- rubygems_version: 2.5.1
226
+ rubygems_version: 3.2.3
227
227
  signing_key:
228
228
  specification_version: 4
229
229
  summary: Rack middleware for server sent events
@@ -231,3 +231,4 @@ test_files:
231
231
  - spec/coverage_helper.rb
232
232
  - spec/middleware_spec.rb
233
233
  - spec/minitest_helper.rb
234
+ - spec/timer_spec.rb