litecable 0.4.2 → 0.7.2

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.
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