litecable 0.4.2 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +38 -1
  3. data/LICENSE.txt +1 -1
  4. data/README.md +27 -28
  5. data/lib/lite_cable.rb +23 -2
  6. data/lib/lite_cable/anycable.rb +22 -13
  7. data/lib/lite_cable/broadcast_adapters.rb +35 -0
  8. data/lib/lite_cable/broadcast_adapters/any_cable.rb +11 -0
  9. data/lib/lite_cable/broadcast_adapters/base.rb +17 -0
  10. data/lib/lite_cable/broadcast_adapters/memory.rb +11 -0
  11. data/lib/lite_cable/channel.rb +1 -0
  12. data/lib/lite_cable/channel/base.rb +4 -2
  13. data/lib/lite_cable/channel/registry.rb +5 -0
  14. data/lib/lite_cable/channel/streams.rb +1 -2
  15. data/lib/lite_cable/coders.rb +1 -0
  16. data/lib/lite_cable/coders/json.rb +1 -0
  17. data/lib/lite_cable/coders/raw.rb +2 -1
  18. data/lib/lite_cable/config.rb +8 -6
  19. data/lib/lite_cable/connection.rb +1 -0
  20. data/lib/lite_cable/connection/authorization.rb +1 -0
  21. data/lib/lite_cable/connection/base.rb +2 -2
  22. data/lib/lite_cable/connection/identification.rb +3 -0
  23. data/lib/lite_cable/connection/streams.rb +1 -0
  24. data/lib/lite_cable/connection/subscriptions.rb +10 -5
  25. data/lib/lite_cable/internal.rb +1 -0
  26. data/lib/lite_cable/logging.rb +4 -2
  27. data/lib/lite_cable/server.rb +1 -6
  28. data/lib/lite_cable/server/client_socket.rb +1 -0
  29. data/lib/lite_cable/server/client_socket/base.rb +17 -21
  30. data/lib/lite_cable/server/client_socket/subscriptions.rb +3 -2
  31. data/lib/lite_cable/server/heart_beat.rb +4 -1
  32. data/lib/lite_cable/server/middleware.rb +7 -6
  33. data/lib/lite_cable/server/subscribers_map.rb +3 -0
  34. data/lib/lite_cable/version.rb +2 -1
  35. data/lib/litecable.rb +1 -0
  36. metadata +28 -75
  37. data/.gem_release.yml +0 -3
  38. data/.gitignore +0 -40
  39. data/.rubocop.yml +0 -63
  40. data/.travis.yml +0 -7
  41. data/Gemfile +0 -4
  42. data/Rakefile +0 -6
  43. data/bin/console +0 -14
  44. data/bin/setup +0 -8
  45. data/circle.yml +0 -8
  46. data/examples/sinatra/Gemfile +0 -16
  47. data/examples/sinatra/Procfile +0 -3
  48. data/examples/sinatra/README.md +0 -33
  49. data/examples/sinatra/anycable +0 -18
  50. data/examples/sinatra/app.rb +0 -52
  51. data/examples/sinatra/assets/app.css +0 -169
  52. data/examples/sinatra/assets/cable.js +0 -584
  53. data/examples/sinatra/assets/reset.css +0 -223
  54. data/examples/sinatra/bin/anycable-go +0 -0
  55. data/examples/sinatra/chat.rb +0 -39
  56. data/examples/sinatra/config.ru +0 -28
  57. data/examples/sinatra/views/index.slim +0 -8
  58. data/examples/sinatra/views/layout.slim +0 -15
  59. data/examples/sinatra/views/login.slim +0 -8
  60. data/examples/sinatra/views/resetcss.slim +0 -224
  61. data/examples/sinatra/views/room.slim +0 -68
  62. data/litecable.gemspec +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: bb4185917544c4f463632a1b1013df954e4e33cd
4
- data.tar.gz: 03a56b7e69b7e9b5b4bd6034106790f161ef1ab8
2
+ SHA256:
3
+ metadata.gz: 0f2e128a054097e5ccd19b490792950d8f8cb53f36d3c6d5c56113271e6f9bb9
4
+ data.tar.gz: bb9439ac1dad7d8be53173b942362eba9a3869674cd598a37a3bda9071efdeff
5
5
  SHA512:
6
- metadata.gz: cedbf509d8ed3b1498ce07de93604498f8f86cba3a1655624c65aa4d0b156e2f386a58e41bbfbc0346512ee58e27b78accf78163ef56d97a9f5f6fcdef1c99e6
7
- data.tar.gz: bb8b8afb66153923fbfe1a1109d6dbc63d6100dd99743e321066f1ee34a8b3809868d31a3a302bb9dd7afba775e4da03aba329dc6bdbdb1dab4ca459d3dd2a45
6
+ metadata.gz: 430ea53e7ebbc00b1f2df127b642235200fb55e9710813d88c4182d337d38d8202b2fac0aadae6d6119e35a612a25c77e10146c1039bba130595e5e28e4579cb
7
+ data.tar.gz: c31bc0b7b6fa0f33754915966bb8e16199dac3ceab604270e9df24c52b2b1b91267e5c32a1cbd5e91dfbb7b5a3f2f074649a8ec7f0d4ac13db68da5ebbe24410
data/CHANGELOG.md CHANGED
@@ -1,8 +1,45 @@
1
1
  # Change log
2
2
 
3
+ ## master (unreleased)
4
+
5
+ ## 0.7.2 (2021-07-06)
6
+
7
+ - Fixed Ruby 3.0.1 compatibility.
8
+
9
+ ## 0.7.1 (2021-01-06)
10
+
11
+ - Fix handling client disconnection during socket write. ([@palkan][])
12
+
13
+ ## 0.7.0 (2020-01-07)
14
+
15
+ - Refactor AnyCable integration ([@palkan][])
16
+
17
+ Now you only need to set AnyCable broadcast adapter:
18
+
19
+ ```ruby
20
+ LiteCable.broadcast_adapter = :any_cable
21
+ ```
22
+
23
+ ```sh
24
+ # or via env/config
25
+ LITECABLE_BROADCAST_ADAPTER=any_cable ruby my_app.rb
26
+ ```
27
+
28
+ - Adapterize broadcast adapters ([@palkan][])
29
+
30
+ - Drop Ruby 2.4 support ([palkan][])
31
+
32
+ ## 0.6.0 (2019-04-12) 🚀
33
+
34
+ - Drop Ruby 2.3 support ([@palkan][])
35
+
36
+ ## 0.5.0 (2017-12-20)
37
+
38
+ - Upgrade for AnyCable 0.5.0 ([@palkan][])
39
+
3
40
  ## 0.4.1 (2017-02-04)
4
41
 
5
- - Use `websocket-ruby` with subprotocols support ([@palkan][])
42
+ - Use `websocket-ruby` with sub-protocols support ([@palkan][])
6
43
 
7
44
  ## 0.4.0 (2017-01-29)
8
45
 
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2017 palkan
3
+ Copyright (c) 2017-2020 palkan
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
- [![Gem Version](https://badge.fury.io/rb/litecable.svg)](https://rubygems.org/gems/litecable) [![Build Status](https://travis-ci.org/palkan/litecable.svg?branch=master)](https://travis-ci.org/palkan/litecable) [![Circle CI](https://circleci.com/gh/palkan/litecable/tree/master.svg?style=svg)](https://circleci.com/gh/palkan/litecable/tree/master)
2
- [![Dependency Status](https://dependencyci.com/github/palkan/litecable/badge)](https://dependencyci.com/github/palkan/litecable)
1
+ [![Gem Version](https://badge.fury.io/rb/litecable.svg)](https://rubygems.org/gems/litecable)
2
+ [![Build](https://github.com/palkan/litecable/workflows/Build/badge.svg)](https://github.com/palkan/litecable/actions)
3
3
 
4
4
  # Lite Cable
5
5
 
@@ -23,20 +23,14 @@ Compatible with [AnyCable](http://anycable.io) (for production usage).
23
23
  Add this line to your application's Gemfile:
24
24
 
25
25
  ```ruby
26
- gem 'litecable'
26
+ gem "litecable"
27
27
  ```
28
28
 
29
- And then execute:
30
-
31
- $ bundle
32
-
33
- Or install it yourself as:
34
-
35
- $ gem install litecable
29
+ And run `bundle install`.
36
30
 
37
31
  ## Usage
38
32
 
39
- 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 _ligthness_.
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_.
40
34
 
41
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)).
42
36
 
@@ -74,36 +68,42 @@ To use Lite Cable server:
74
68
 
75
69
  ```ruby
76
70
  Rack::Builder.new do
77
- map '/cable' do
71
+ map "/cable" do
78
72
  # You have to specify your app's connection class
79
73
  use LiteCable::Server::Middleware, connection_class: App::Connection
80
- run proc { |_| [200, { 'Content-Type' => 'text/plain' }, ['OK']] }
74
+ run proc { |_| [200, {"Content-Type" => "text/plain"}, ["OK"]] }
81
75
  end
82
76
  end
83
77
  ```
84
78
 
85
79
  ### Using with AnyCable
86
80
 
87
- Lite Cable is AnyCable-compatible out-of-the-box. You should write a simple server script:
81
+ Lite Cable is AnyCable-compatible out-of-the-box:
82
+
83
+ - Set broadcast adapter to AnyCable:
88
84
 
89
85
  ```ruby
90
- #!/usr/bin/env ruby
86
+ LiteCable.broadcast_adapter = :any_cable
87
+ ```
91
88
 
92
- require "my_app"
93
- require "rack"
94
- 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.
95
90
 
96
- # Turn AnyCable compatibility mode
97
- LiteCable.anycable!
91
+ - Configure connection factory:
98
92
 
99
- Anycable.configure do |config|
100
- config.connection_factory = MyApp::Connection
101
- end
93
+ ```ruby
94
+ AnyCable.connection_factory = MyApp::Connection
95
+ ```
96
+
97
+ Then run AnyCable along with the app:
102
98
 
103
- Anycable::Server.start
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
104
104
  ```
105
105
 
106
- And then run this script along with your application. See [Sinatra example](https://github.com/palkan/litecable/tree/master/examples/sinatra) for more.
106
+ See [Sinatra example](https://github.com/palkan/litecable/tree/master/examples/sinatra) for more.
107
107
 
108
108
  ### Configuration
109
109
 
@@ -123,9 +123,8 @@ See [config](https://github.com/palkan/litecable/blob/master/lib/lite_cable/conf
123
123
 
124
124
  ## Contributing
125
125
 
126
- Bug reports and pull requests are welcome on GitHub at https://github.com/anycable/litecable.
126
+ Bug reports and pull requests are welcome on GitHub at [https://github.com/palkan/litecable](https://github.com/palkan/litecable).
127
127
 
128
128
  ## License
129
129
 
130
- The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
131
-
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(*args)
26
- LiteCable::Server.broadcast(*args)
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
@@ -1,20 +1,14 @@
1
1
  # frozen_string_literal: true
2
- module LiteCable
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 create(socket, **options)
11
+ def call(socket, **options)
18
12
  new(socket, **options)
19
13
  end
20
14
 
@@ -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
- LiteCable::Channel::Error,
48
- LiteCable::Channel::Registry::Error => e
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 with AnyCable functionality
53
+ # Patch Lite Cable with AnyCable functionality
58
54
  def self.anycable!
59
55
  LiteCable::Connection::Base.extend LiteCable::AnyCable::Connection
60
- LiteCable.singleton_class.prepend LiteCable::AnyCable::Broadcasting
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
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LiteCable
4
+ module BroadcastAdapters
5
+ class AnyCable < Base
6
+ def broadcast(stream, message, coder:)
7
+ ::AnyCable.broadcast stream, coder.encode(message)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ # frozen_string_literal: true
4
+
5
+ module LiteCable
6
+ module BroadcastAdapters
7
+ class Base
8
+ def initialize(**options)
9
+ @options = options
10
+ end
11
+
12
+ private
13
+
14
+ attr_reader :options
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LiteCable
4
+ module BroadcastAdapters
5
+ class Memory < Base
6
+ def broadcast(stream, message, coder:)
7
+ Server.subscribers_map.broadcast stream, message, coder
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module LiteCable
3
4
  module Channel # :nodoc:
4
5
  require "lite_cable/channel/registry"
@@ -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