litecable 0.4.1 → 0.7.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 +5 -5
- data/CHANGELOG.md +34 -1
- data/LICENSE.txt +1 -1
- data/README.md +30 -28
- data/lib/lite_cable.rb +23 -2
- data/lib/lite_cable/anycable.rb +23 -14
- data/lib/lite_cable/broadcast_adapters.rb +35 -0
- data/lib/lite_cable/broadcast_adapters/any_cable.rb +11 -0
- data/lib/lite_cable/broadcast_adapters/base.rb +17 -0
- data/lib/lite_cable/broadcast_adapters/memory.rb +11 -0
- data/lib/lite_cable/channel.rb +1 -0
- data/lib/lite_cable/channel/base.rb +4 -2
- data/lib/lite_cable/channel/registry.rb +5 -0
- data/lib/lite_cable/channel/streams.rb +1 -2
- data/lib/lite_cable/coders.rb +1 -0
- data/lib/lite_cable/coders/json.rb +1 -0
- data/lib/lite_cable/coders/raw.rb +2 -1
- data/lib/lite_cable/config.rb +8 -6
- data/lib/lite_cable/connection.rb +1 -0
- data/lib/lite_cable/connection/authorization.rb +1 -0
- data/lib/lite_cable/connection/base.rb +2 -2
- data/lib/lite_cable/connection/identification.rb +3 -0
- data/lib/lite_cable/connection/streams.rb +1 -0
- data/lib/lite_cable/connection/subscriptions.rb +7 -2
- data/lib/lite_cable/internal.rb +1 -0
- data/lib/lite_cable/logging.rb +4 -2
- data/lib/lite_cable/server.rb +1 -6
- data/lib/lite_cable/server/client_socket.rb +1 -0
- data/lib/lite_cable/server/client_socket/base.rb +17 -21
- data/lib/lite_cable/server/client_socket/subscriptions.rb +3 -2
- data/lib/lite_cable/server/heart_beat.rb +4 -1
- data/lib/lite_cable/server/middleware.rb +7 -6
- data/lib/lite_cable/server/subscribers_map.rb +3 -0
- data/lib/lite_cable/version.rb +2 -1
- data/lib/litecable.rb +1 -0
- metadata +31 -77
- data/.gitignore +0 -40
- data/.rubocop.yml +0 -63
- data/.travis.yml +0 -7
- data/Gemfile +0 -4
- data/Rakefile +0 -6
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/circle.yml +0 -8
- data/examples/sinatra/Gemfile +0 -16
- data/examples/sinatra/Procfile +0 -3
- data/examples/sinatra/README.md +0 -33
- data/examples/sinatra/anycable +0 -18
- data/examples/sinatra/app.rb +0 -52
- data/examples/sinatra/assets/app.css +0 -169
- data/examples/sinatra/assets/cable.js +0 -584
- data/examples/sinatra/assets/reset.css +0 -223
- data/examples/sinatra/bin/anycable-go +0 -0
- data/examples/sinatra/chat.rb +0 -39
- data/examples/sinatra/config.ru +0 -28
- data/examples/sinatra/views/index.slim +0 -8
- data/examples/sinatra/views/layout.slim +0 -15
- data/examples/sinatra/views/login.slim +0 -8
- data/examples/sinatra/views/resetcss.slim +0 -224
- data/examples/sinatra/views/room.slim +0 -68
- data/litecable.gemspec +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 94ece0fdf218bcdeefe8b375d73114c28bd869c5d232d1c38dd91f0e880c1e57
|
4
|
+
data.tar.gz: e53c002d7179a52793a1382dd88dbb782d43319801e0f5ff51d36dd32237c005
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1867f388377ea2f29c63cea936e255dcea9b7011ce83a45f93965ee98507c00e063360d62fb436a80a767c52b23f00ff853e92dbb93421ab9b0f007243cbc1d7
|
7
|
+
data.tar.gz: 9d344ce7aa7f3f0c07dc8c6be396cd51ae18758ffd5ad3e07ff156704fe87ee4ab0d54c67f0e619b30cb5344635f39860df0919b6a9587230ae87aa7d226d0c7
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,41 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
|
+
## master (unreleased)
|
4
|
+
|
5
|
+
## 0.7.1 (2021-01-06)
|
6
|
+
|
7
|
+
- Fix handling client disconnection during socket write. ([@palkan][])
|
8
|
+
|
9
|
+
## 0.7.0 (2020-01-07)
|
10
|
+
|
11
|
+
- Refactor AnyCable integration ([@palkan][])
|
12
|
+
|
13
|
+
Now you only need to set AnyCable broadcast adapter:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
LiteCable.broadcast_adapter = :any_cable
|
17
|
+
```
|
18
|
+
|
19
|
+
```sh
|
20
|
+
# or via env/config
|
21
|
+
LITECABLE_BROADCAST_ADAPTER=any_cable ruby my_app.rb
|
22
|
+
```
|
23
|
+
|
24
|
+
- Adapterize broadcast adapters ([@palkan][])
|
25
|
+
|
26
|
+
- Drop Ruby 2.4 support ([palkan][])
|
27
|
+
|
28
|
+
## 0.6.0 (2019-04-12) 🚀
|
29
|
+
|
30
|
+
- Drop Ruby 2.3 support ([@palkan][])
|
31
|
+
|
32
|
+
## 0.5.0 (2017-12-20)
|
33
|
+
|
34
|
+
- Upgrade for AnyCable 0.5.0 ([@palkan][])
|
35
|
+
|
3
36
|
## 0.4.1 (2017-02-04)
|
4
37
|
|
5
|
-
- Use `websocket-ruby` with
|
38
|
+
- Use `websocket-ruby` with sub-protocols support ([@palkan][])
|
6
39
|
|
7
40
|
## 0.4.0 (2017-01-29)
|
8
41
|
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
[](https://rubygems.org/gems/litecable)
|
1
|
+
[](https://rubygems.org/gems/litecable)
|
2
|
+
[](https://github.com/palkan/litecable/actions)
|
2
3
|
|
3
4
|
# Lite Cable
|
4
5
|
|
@@ -13,27 +14,23 @@ Compatible with [AnyCable](http://anycable.io) (for production usage).
|
|
13
14
|
|
14
15
|
## Examples
|
15
16
|
|
16
|
-
- [Sinatra
|
17
|
+
- [Sinatra LiteCable Chat](https://github.com/palkan/litecable/tree/master/examples/sinatra)
|
18
|
+
|
19
|
+
- [Connecting LiteCable to Hanami](http://gabrielmalakias.com.br/ruby/hanami/iot/2017/05/26/websockets-connecting-litecable-to-hanami.html) by [@GabrielMalakias](https://github.com/GabrielMalakias)
|
17
20
|
|
18
21
|
## Installation
|
19
22
|
|
20
23
|
Add this line to your application's Gemfile:
|
21
24
|
|
22
25
|
```ruby
|
23
|
-
gem
|
26
|
+
gem "litecable"
|
24
27
|
```
|
25
28
|
|
26
|
-
And
|
27
|
-
|
28
|
-
$ bundle
|
29
|
-
|
30
|
-
Or install it yourself as:
|
31
|
-
|
32
|
-
$ gem install litecable
|
29
|
+
And run `bundle install`.
|
33
30
|
|
34
31
|
## Usage
|
35
32
|
|
36
|
-
Please, checkout [Action Cable guides](http://guides.rubyonrails.org/action_cable_overview.html) for general information. Lite Cable aims to be compatible with Action Cable as much as possible without the loss of simplicity and
|
33
|
+
Please, checkout [Action Cable guides](http://guides.rubyonrails.org/action_cable_overview.html) for general information. Lite Cable aims to be compatible with Action Cable as much as possible without the loss of simplicity and _lightness_.
|
37
34
|
|
38
35
|
You can use Action Cable javascript client without any change (precompiled version can be found [here](https://github.com/palkan/litecable/tree/master/examples/sinatra/assets/cable.js)).
|
39
36
|
|
@@ -71,36 +68,42 @@ To use Lite Cable server:
|
|
71
68
|
|
72
69
|
```ruby
|
73
70
|
Rack::Builder.new do
|
74
|
-
map
|
71
|
+
map "/cable" do
|
75
72
|
# You have to specify your app's connection class
|
76
73
|
use LiteCable::Server::Middleware, connection_class: App::Connection
|
77
|
-
run proc { |_| [200, {
|
74
|
+
run proc { |_| [200, {"Content-Type" => "text/plain"}, ["OK"]] }
|
78
75
|
end
|
79
76
|
end
|
80
77
|
```
|
81
78
|
|
82
79
|
### Using with AnyCable
|
83
80
|
|
84
|
-
Lite Cable is AnyCable-compatible out-of-the-box
|
81
|
+
Lite Cable is AnyCable-compatible out-of-the-box:
|
82
|
+
|
83
|
+
- Set broadcast adapter to AnyCable:
|
85
84
|
|
86
85
|
```ruby
|
87
|
-
|
86
|
+
LiteCable.broadcast_adapter = :any_cable
|
87
|
+
```
|
88
88
|
|
89
|
-
|
90
|
-
require "rack"
|
91
|
-
require "anycable"
|
89
|
+
You can also do this via configuration, e.g., env var (`LITECABLE_BROADCAST_ADAPTER=any_cable`) or `broadcast_adapter: any_cable` in a YAML config.
|
92
90
|
|
93
|
-
|
94
|
-
LiteCable.anycable!
|
91
|
+
- Configure connection factory:
|
95
92
|
|
96
|
-
|
97
|
-
|
98
|
-
|
93
|
+
```ruby
|
94
|
+
AnyCable.connection_factory = MyApp::Connection
|
95
|
+
```
|
99
96
|
|
100
|
-
|
97
|
+
Then run AnyCable along with the app:
|
98
|
+
|
99
|
+
```sh
|
100
|
+
bundle exec anycable
|
101
|
+
|
102
|
+
# add -r option to load the app if it's not ./config/anycable.rb or ./config/environment.rb
|
103
|
+
bundle exec anycable -r ./my_app.rb
|
101
104
|
```
|
102
105
|
|
103
|
-
|
106
|
+
See [Sinatra example](https://github.com/palkan/litecable/tree/master/examples/sinatra) for more.
|
104
107
|
|
105
108
|
### Configuration
|
106
109
|
|
@@ -120,9 +123,8 @@ See [config](https://github.com/palkan/litecable/blob/master/lib/lite_cable/conf
|
|
120
123
|
|
121
124
|
## Contributing
|
122
125
|
|
123
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
126
|
+
Bug reports and pull requests are welcome on GitHub at [https://github.com/palkan/litecable](https://github.com/palkan/litecable).
|
124
127
|
|
125
128
|
## License
|
126
129
|
|
127
|
-
The gem is available as open source under the terms of the [MIT License](
|
128
|
-
|
130
|
+
The gem is available as open source under the terms of the [MIT License](./LICENSE.txt).
|
data/lib/lite_cable.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "lite_cable/version"
|
3
4
|
require "lite_cable/internal"
|
4
5
|
require "lite_cable/logging"
|
@@ -14,6 +15,7 @@ module LiteCable
|
|
14
15
|
require "lite_cable/channel"
|
15
16
|
require "lite_cable/coders"
|
16
17
|
require "lite_cable/config"
|
18
|
+
require "lite_cable/broadcast_adapters"
|
17
19
|
require "lite_cable/anycable"
|
18
20
|
|
19
21
|
class << self
|
@@ -22,8 +24,27 @@ module LiteCable
|
|
22
24
|
end
|
23
25
|
|
24
26
|
# Broadcast encoded message to the stream
|
25
|
-
def broadcast(
|
26
|
-
|
27
|
+
def broadcast(stream, message, coder: LiteCable.config.coder)
|
28
|
+
broadcast_adapter.broadcast(stream, message, coder: coder)
|
29
|
+
end
|
30
|
+
|
31
|
+
def broadcast_adapter
|
32
|
+
return @broadcast_adapter if defined?(@broadcast_adapter)
|
33
|
+
self.broadcast_adapter = LiteCable.config.broadcast_adapter.to_sym
|
34
|
+
@broadcast_adapter
|
35
|
+
end
|
36
|
+
|
37
|
+
def broadcast_adapter=(adapter)
|
38
|
+
if adapter.is_a?(Symbol) || adapter.is_a?(Array)
|
39
|
+
adapter = BroadcastAdapters.lookup_adapter(adapter)
|
40
|
+
end
|
41
|
+
|
42
|
+
unless adapter.respond_to?(:broadcast)
|
43
|
+
raise ArgumentError, "BroadcastAdapter must implement #broadcast method. " \
|
44
|
+
"#{adapter.class} doesn't implement it."
|
45
|
+
end
|
46
|
+
|
47
|
+
@broadcast_adapter = adapter
|
27
48
|
end
|
28
49
|
end
|
29
50
|
end
|
data/lib/lite_cable/anycable.rb
CHANGED
@@ -1,21 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
|
3
|
+
module LiteCable # :nodoc:
|
3
4
|
# AnyCable extensions
|
4
5
|
module AnyCable
|
5
|
-
module Broadcasting # :nodoc:
|
6
|
-
def broadcast(stream, message, coder: nil)
|
7
|
-
coder ||= LiteCable.config.coder
|
8
|
-
Anycable.broadcast stream, coder.encode(message)
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
6
|
module Connection # :nodoc:
|
13
7
|
def self.extended(base)
|
14
8
|
base.prepend InstanceMethods
|
15
9
|
end
|
16
10
|
|
17
|
-
def
|
18
|
-
new(socket,
|
11
|
+
def call(socket, **options)
|
12
|
+
new(socket, options)
|
19
13
|
end
|
20
14
|
|
21
15
|
module InstanceMethods # :nodoc:
|
@@ -29,6 +23,7 @@ module LiteCable
|
|
29
23
|
@request ||= Rack::Request.new(socket.env)
|
30
24
|
end
|
31
25
|
|
26
|
+
# rubocop: disable Metrics/MethodLength
|
32
27
|
def handle_channel_command(identifier, command, data)
|
33
28
|
channel = subscriptions.add(identifier, false)
|
34
29
|
case command
|
@@ -44,19 +39,33 @@ module LiteCable
|
|
44
39
|
false
|
45
40
|
end
|
46
41
|
rescue LiteCable::Connection::Subscriptions::Error,
|
47
|
-
|
48
|
-
|
42
|
+
LiteCable::Channel::Error,
|
43
|
+
LiteCable::Channel::Registry::Error => e
|
49
44
|
log(:error, log_fmt("Connection command failed: #{e}"))
|
50
45
|
close
|
51
46
|
false
|
52
47
|
end
|
48
|
+
# rubocop: enable Metrics/MethodLength
|
53
49
|
end
|
54
50
|
end
|
55
51
|
end
|
56
52
|
|
57
|
-
# Patch Lite Cable
|
53
|
+
# Patch Lite Cable with AnyCable functionality
|
58
54
|
def self.anycable!
|
59
55
|
LiteCable::Connection::Base.extend LiteCable::AnyCable::Connection
|
60
|
-
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
if defined?(AnyCable)
|
60
|
+
AnyCable.configure_server do
|
61
|
+
# Make sure broadcast adapter is valid
|
62
|
+
require "lite_cable/broadcast_adapters/any_cable"
|
63
|
+
unless LiteCable::BroadcastAdapters::AnyCable === LiteCable.broadcast_adapter
|
64
|
+
raise "You should use :any_cable broadcast adapter (current: #{LiteCable.broadcast_adapter.class}). " \
|
65
|
+
"Set it via LITECABLE_BROADCAST_ADAPTER=any_cable or in the code/YML."
|
66
|
+
end
|
67
|
+
|
68
|
+
# Turn AnyCable compatibility mode for anycable RPC server automatically
|
69
|
+
LiteCable.anycable!
|
61
70
|
end
|
62
71
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "lite_cable/broadcast_adapters/base"
|
4
|
+
|
5
|
+
module LiteCable
|
6
|
+
module BroadcastAdapters # :nodoc:
|
7
|
+
module_function
|
8
|
+
|
9
|
+
# rubocop: disable Metrics/AbcSize, Metrics/MethodLength
|
10
|
+
def lookup_adapter(args)
|
11
|
+
adapter, options = Array(args)
|
12
|
+
path_to_adapter = "lite_cable/broadcast_adapters/#{adapter}"
|
13
|
+
adapter_class_name = adapter.to_s.split("_").map(&:capitalize).join
|
14
|
+
|
15
|
+
unless BroadcastAdapters.const_defined?(adapter_class_name, false)
|
16
|
+
begin
|
17
|
+
require path_to_adapter
|
18
|
+
rescue LoadError => e
|
19
|
+
# We couldn't require the adapter itself.
|
20
|
+
if e.path == path_to_adapter
|
21
|
+
raise e.class, "Couldn't load the '#{adapter}' broadcast adapter for LiteCable",
|
22
|
+
e.backtrace
|
23
|
+
# Bubbled up from the adapter require.
|
24
|
+
else
|
25
|
+
raise e.class, "Error loading the '#{adapter}' broadcast adapter for LiteCable",
|
26
|
+
e.backtrace
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
BroadcastAdapters.const_get(adapter_class_name, false).new(**(options || {}))
|
32
|
+
end
|
33
|
+
# rubocop: enable Metrics/AbcSize, Metrics/MethodLength
|
34
|
+
end
|
35
|
+
end
|
data/lib/lite_cable/channel.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module LiteCable
|
3
|
-
# rubocop:disable Metrics/LineLength
|
4
4
|
module Channel
|
5
5
|
class Error < StandardError; end
|
6
|
+
|
6
7
|
class RejectedError < Error; end
|
8
|
+
|
7
9
|
class UnproccessableActionError < Error; end
|
8
10
|
|
9
11
|
# The channel provides the basic structure of grouping behavior into logical units when communicating over the connection.
|
@@ -62,7 +64,6 @@ module LiteCable
|
|
62
64
|
# client-side, the <tt>Channel#rejected</tt> callback will get invoked when
|
63
65
|
# the server rejects the subscription request.
|
64
66
|
class Base
|
65
|
-
# rubocop:enable Metrics/LineLength
|
66
67
|
class << self
|
67
68
|
# A set of method names that should be considered actions.
|
68
69
|
# This includes all public instance methods on a channel except from Channel::Base methods.
|
@@ -128,6 +129,7 @@ module LiteCable
|
|
128
129
|
action = extract_action(data)
|
129
130
|
|
130
131
|
raise UnproccessableActionError unless processable_action?(action)
|
132
|
+
|
131
133
|
log(:debug) { log_fmt("Perform action #{action}(#{data})") }
|
132
134
|
dispatch_action(action, data)
|
133
135
|
end
|
@@ -1,15 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module LiteCable
|
3
4
|
module Channel
|
4
5
|
# Stores channels identifiers and corresponding classes.
|
5
6
|
module Registry
|
6
7
|
class Error < StandardError; end
|
8
|
+
|
7
9
|
class AlreadyRegisteredError < Error; end
|
10
|
+
|
8
11
|
class UnknownChannelError < Error; end
|
9
12
|
|
10
13
|
class << self
|
11
14
|
def add(id, channel_class)
|
12
15
|
raise AlreadyRegisteredError if find(id)
|
16
|
+
|
13
17
|
channels[id] = channel_class
|
14
18
|
end
|
15
19
|
|
@@ -20,6 +24,7 @@ module LiteCable
|
|
20
24
|
def find!(id)
|
21
25
|
channel_class = find(id)
|
22
26
|
raise UnknownChannelError unless channel_class
|
27
|
+
|
23
28
|
channel_class
|
24
29
|
end
|
25
30
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module LiteCable
|
3
|
-
# rubocop:disable Metrics/LineLength
|
4
4
|
module Channel
|
5
5
|
# Streams allow channels to route broadcastings to the subscriber. A broadcasting is a pubsub queue where any data
|
6
6
|
# placed into it is automatically sent to the clients that are connected at that time.
|
@@ -28,7 +28,6 @@ module LiteCable
|
|
28
28
|
#
|
29
29
|
# You can stop streaming from all broadcasts by calling #stop_all_streams or use #stop_from to stop streaming broadcasts from the specified stream.
|
30
30
|
module Streams
|
31
|
-
# rubocop:enable Metrics/LineLength
|
32
31
|
def handle_unsubscribe
|
33
32
|
stop_all_streams
|
34
33
|
super
|