rasti-web-broadcaster 1.1.2 → 2.0.1

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
2
  SHA256:
3
- metadata.gz: 0e5290c1fe92680bd88bd05f57f91b1d49a6848516865a6da8cfdb8d47cf6f44
4
- data.tar.gz: eef7f1069f999eddd07fe89a7d6059e95bd669fbae2030f75d2fef0b180bf2b5
3
+ metadata.gz: b4274cbf5d65945a27bddcaa7372223972319791e59d74cf87a44b3782ccfd8c
4
+ data.tar.gz: 1ae384e5c92f88234341f3c7c610409ae0c16aff25d0c1df42fac452f615f85a
5
5
  SHA512:
6
- metadata.gz: db5ca61f44dcb3ebaab5557cca6c245a8e7bccca22833b2aaa0aa38428a0baa5e0c9b0f7c8133ac7fb7e132a2ee173d39e4135a486b747209ed90cadd2d71b60
7
- data.tar.gz: 06bebe40478194b3dceea7fd7a2b670cd75997630170d7ab54b72f7142c57bcdaf3b94a2d6969bf26de1f3c3eeddd581a2bbe338fe205cf251fe14c6cc6db313
6
+ metadata.gz: fcc2e8c4646744d1016bc3e17e63f5dcf6ebf95703efbe8f0c0434cf2ac9c262266e6b1cbc3e2a6b86a726b448162c97d8d723a6dccfe48618de7e657eb248df
7
+ data.tar.gz: fadc9eeb6b0633864fd6c418a0194a603d8495e627e631fabb16db8ca7ad7d4b615787626de55eb89897ecff264ff0cb247197c03304aefd3c8ea03644926e75
@@ -0,0 +1,37 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ '**' ]
6
+ pull_request:
7
+ branches: [ '**' ]
8
+
9
+ jobs:
10
+ test:
11
+
12
+ name: Tests
13
+ runs-on: ubuntu-22.04
14
+ strategy:
15
+ matrix:
16
+ ruby-version: ['2.3', '2.4', '2.5', '2.6', '2.7', '3.0', 'jruby-9.2.9.0']
17
+
18
+ services:
19
+ redis:
20
+ image: redis:7
21
+ ports:
22
+ - 6379:6379
23
+ options: >-
24
+ --health-cmd "redis-cli ping"
25
+ --health-interval 10s
26
+ --health-timeout 5s
27
+ --health-retries 3
28
+
29
+ steps:
30
+ - uses: actions/checkout@v3
31
+ - name: Set up Ruby
32
+ uses: ruby/setup-ruby@v1
33
+ with:
34
+ ruby-version: ${{ matrix.ruby-version }}
35
+ bundler-cache: true
36
+ - name: Run tests
37
+ run: bundle exec rake
data/README.md CHANGED
@@ -1,9 +1,7 @@
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)
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
- [![Code Climate](https://codeclimate.com/github/gabynaiman/rasti-web-broadcaster.svg)](https://codeclimate.com/github/gabynaiman/rasti-web-broadcaster)
4
+ [![CI](https://github.com/gabynaiman/rasti-web-broadcaster/actions/workflows/ci.yml/badge.svg)](https://github.com/gabynaiman/rasti-web-broadcaster/actions/workflows/ci.yml)
7
5
 
8
6
  Enable server sent events with rack middleware implemented over Faye and Broadcaster (Redis Pub/Sub)
9
7
 
@@ -30,6 +28,7 @@ Or install it yourself as:
30
28
  Rasti::Web::Broadcaster.configure do |config|
31
29
  config.id = 'AppName'
32
30
  config.redis_settings = "redis://#{ENV['REDIS_HOST']}:#{ENV['REDIS_PORT']}"
31
+ config.keep_alive_interval = 30
33
32
  config.logger = Logger.new "/log/#{ENV['RACK_ENV']}.log"
34
33
  end
35
34
  ```
@@ -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.2'
4
+ VERSION = '2.0.1'
5
5
  end
6
6
  end
7
7
  end
@@ -4,18 +4,22 @@ require 'class_config'
4
4
 
5
5
  require_relative 'broadcaster/safe_event_machine'
6
6
  require_relative 'broadcaster/safe_rack_lint'
7
+ require_relative 'broadcaster/timer'
7
8
  require_relative 'broadcaster/version'
8
9
 
9
10
  module Rasti
10
11
  module Web
11
12
  class Broadcaster
12
13
 
14
+ KEEP_ALIVE_EVENT = 'keepAlive'
15
+
13
16
  extend ClassConfig
14
17
 
15
- attr_config :id, 'rasti.web.broadcaster'
16
- attr_config :redis_client, Redic
17
- attr_config :redis_settings, 'redis://localhost:6379'
18
- 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
19
23
 
20
24
  @mutex = Mutex.new
21
25
 
@@ -23,8 +27,8 @@ module Rasti
23
27
 
24
28
  extend Forwardable
25
29
 
26
- def_delegators :broadcaster, :subscribe,
27
- :unsubscribe,
30
+ def_delegators :broadcaster, :subscribe,
31
+ :unsubscribe,
28
32
  :publish
29
33
 
30
34
  private
@@ -40,20 +44,20 @@ module Rasti
40
44
  def initialize(app, headers={})
41
45
  @app = app
42
46
  @headers = headers
47
+ @mutex = Mutex.new
48
+ @subscriptions = {}
49
+
50
+ start_sending_keep_alive_messages
43
51
  end
44
52
 
45
53
  def call(env)
46
54
  if Faye::EventSource.eventsource? env
47
- event_source = Faye::EventSource.new env, headers: @headers
48
- channel = env['PATH_INFO'][1..-1]
55
+ event_source = Faye::EventSource.new env, headers: headers
49
56
 
50
- subscription_id = self.class.subscribe channel do |message|
51
- event_source.send message[:data], event: message[:event],
52
- id: message[:id]
53
- end
57
+ subscription_id = subscribe channel_from(env), event_source
54
58
 
55
59
  event_source.on :close do
56
- self.class.unsubscribe subscription_id
60
+ unsubscribe subscription_id
57
61
  event_source = nil
58
62
  end
59
63
 
@@ -65,7 +69,42 @@ module Rasti
65
69
 
66
70
  private
67
71
 
68
- 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
+ self.class.logger.info(self.class) { "Sending message to #{subscription_id} | Channel: #{channel} | Message: #{message}" }
77
+ send_message(event_source, **message)
78
+ end
79
+
80
+ mutex.synchronize { subscriptions[subscription_id] = event_source }
81
+
82
+ subscription_id
83
+ end
84
+
85
+ def unsubscribe(subscription_id)
86
+ self.class.unsubscribe subscription_id
87
+ mutex.synchronize { subscriptions.delete subscription_id }
88
+ end
89
+
90
+ def send_message(event_source, data:, event: nil, id: nil)
91
+ event_source.send data, event: event, id: id
92
+ end
93
+
94
+ def start_sending_keep_alive_messages
95
+ if self.class.keep_alive_interval
96
+ Timer.every self.class.keep_alive_interval do
97
+ subscriptions.each do |subscription_id, event_source|
98
+ self.class.logger.debug(self.class) { "Sending keep alive to #{subscription_id}" }
99
+ send_message event_source, data: '', event: KEEP_ALIVE_EVENT
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ def channel_from(env)
106
+ env['PATH_INFO'][1..-1]
107
+ end
69
108
 
70
109
  end
71
110
  end
@@ -27,11 +27,6 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency 'minitest-colorin', '~> 0.1'
28
28
  spec.add_development_dependency 'minitest-line', '~> 0.6'
29
29
  spec.add_development_dependency 'simplecov', '~> 0.12'
30
- spec.add_development_dependency 'coveralls', '~> 0.8'
31
30
  spec.add_development_dependency 'pry-nav', '~> 0.2'
32
31
  spec.add_development_dependency 'rack-test', '~> 0.6'
33
-
34
- if RUBY_VERSION < '2.2.2'
35
- spec.add_development_dependency 'rack', '< 2'
36
- end
37
32
  end
@@ -1,5 +1,4 @@
1
1
  require 'simplecov'
2
- require 'coveralls'
3
2
 
4
- SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new [SimpleCov::Formatter::HTMLFormatter, Coveralls::SimpleCov::Formatter]
3
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new [SimpleCov::Formatter::HTMLFormatter]
5
4
  SimpleCov.start
@@ -47,7 +47,7 @@ describe Rasti::Web::Broadcaster do
47
47
  event_source = nil
48
48
  events = []
49
49
 
50
- env['async.callback'] = proc do |(status, headers, body)|
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
@@ -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
69
  event_for(data: 'message 1', event: 'event_1', id: 1),
70
- event_for(data: 'message 3')
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.2
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gabriel Naiman
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-26 00:00:00.000000000 Z
11
+ date: 2025-06-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faye-websocket
@@ -134,20 +134,6 @@ dependencies:
134
134
  - - "~>"
135
135
  - !ruby/object:Gem::Version
136
136
  version: '0.12'
137
- - !ruby/object:Gem::Dependency
138
- name: coveralls
139
- requirement: !ruby/object:Gem::Requirement
140
- requirements:
141
- - - "~>"
142
- - !ruby/object:Gem::Version
143
- version: '0.8'
144
- type: :development
145
- prerelease: false
146
- version_requirements: !ruby/object:Gem::Requirement
147
- requirements:
148
- - - "~>"
149
- - !ruby/object:Gem::Version
150
- version: '0.8'
151
137
  - !ruby/object:Gem::Dependency
152
138
  name: pry-nav
153
139
  requirement: !ruby/object:Gem::Requirement
@@ -184,11 +170,10 @@ executables: []
184
170
  extensions: []
185
171
  extra_rdoc_files: []
186
172
  files:
187
- - ".coveralls.yml"
173
+ - ".github/workflows/ci.yml"
188
174
  - ".gitignore"
189
175
  - ".ruby-gemset"
190
176
  - ".ruby-version"
191
- - ".travis.yml"
192
177
  - Gemfile
193
178
  - LICENSE.txt
194
179
  - README.md
@@ -197,16 +182,18 @@ files:
197
182
  - lib/rasti/web/broadcaster.rb
198
183
  - lib/rasti/web/broadcaster/safe_event_machine.rb
199
184
  - lib/rasti/web/broadcaster/safe_rack_lint.rb
185
+ - lib/rasti/web/broadcaster/timer.rb
200
186
  - lib/rasti/web/broadcaster/version.rb
201
187
  - rasti-web-broadcaster.gemspec
202
188
  - spec/coverage_helper.rb
203
189
  - spec/middleware_spec.rb
204
190
  - spec/minitest_helper.rb
191
+ - spec/timer_spec.rb
205
192
  homepage: https://github.com/gabynaiman/rasti-web-broadcaster
206
193
  licenses:
207
194
  - MIT
208
195
  metadata: {}
209
- post_install_message:
196
+ post_install_message:
210
197
  rdoc_options: []
211
198
  require_paths:
212
199
  - lib
@@ -221,11 +208,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
221
208
  - !ruby/object:Gem::Version
222
209
  version: '0'
223
210
  requirements: []
224
- rubygems_version: 3.0.6
225
- signing_key:
211
+ rubygems_version: 3.0.9
212
+ signing_key:
226
213
  specification_version: 4
227
214
  summary: Rack middleware for server sent events
228
215
  test_files:
229
216
  - spec/coverage_helper.rb
230
217
  - spec/middleware_spec.rb
231
218
  - spec/minitest_helper.rb
219
+ - spec/timer_spec.rb
data/.coveralls.yml DELETED
@@ -1,2 +0,0 @@
1
- service_name: travis-ci
2
- repo_token: lhkQlHPQWvmFvmpjd6kU3IWd9Zo2veQkw
data/.travis.yml DELETED
@@ -1,23 +0,0 @@
1
- language: ruby
2
-
3
- rvm:
4
- - 2.0
5
- - 2.1
6
- - 2.2
7
- - 2.3
8
- - 2.4
9
- - 2.5
10
- - 2.6
11
- - 2.7
12
- - jruby-9.2.9.0
13
- - ruby-head
14
- - jruby-head
15
-
16
- matrix:
17
- fast_finish: true
18
- allow_failures:
19
- - rvm: ruby-head
20
- - rvm: jruby-head
21
-
22
- services:
23
- - redis-server