litecable 0.4.0 → 0.7.0

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 +32 -1
  3. data/LICENSE.txt +1 -1
  4. data/README.md +30 -28
  5. data/lib/lite_cable.rb +23 -2
  6. data/lib/lite_cable/anycable.rb +21 -12
  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 +2 -0
  13. data/lib/lite_cable/channel/registry.rb +3 -0
  14. data/lib/lite_cable/channel/streams.rb +1 -0
  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 +1 -0
  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 -0
  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 +5 -3
  25. data/lib/lite_cable/internal.rb +1 -0
  26. data/lib/lite_cable/logging.rb +3 -1
  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 +16 -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 +11 -10
  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 +31 -50
  37. data/.gitignore +0 -40
  38. data/.rubocop.yml +0 -63
  39. data/.travis.yml +0 -7
  40. data/Gemfile +0 -4
  41. data/Rakefile +0 -6
  42. data/bin/console +0 -14
  43. data/bin/setup +0 -8
  44. data/circle.yml +0 -8
  45. data/examples/sinatra/Gemfile +0 -16
  46. data/examples/sinatra/Procfile +0 -3
  47. data/examples/sinatra/README.md +0 -33
  48. data/examples/sinatra/anycable +0 -18
  49. data/examples/sinatra/app.rb +0 -52
  50. data/examples/sinatra/assets/app.css +0 -169
  51. data/examples/sinatra/assets/cable.js +0 -584
  52. data/examples/sinatra/assets/reset.css +0 -223
  53. data/examples/sinatra/bin/anycable-go +0 -0
  54. data/examples/sinatra/chat.rb +0 -39
  55. data/examples/sinatra/config.ru +0 -28
  56. data/examples/sinatra/views/index.slim +0 -8
  57. data/examples/sinatra/views/layout.slim +0 -15
  58. data/examples/sinatra/views/login.slim +0 -8
  59. data/examples/sinatra/views/resetcss.slim +0 -224
  60. data/examples/sinatra/views/room.slim +0 -68
  61. data/lib/lite_cable/server/websocket_ext/protocols.rb +0 -45
  62. data/litecable.gemspec +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 4640e78d6f9a77cf9257cb0774ff249ec1b5f699
4
- data.tar.gz: a2cc894fc9e355baa79d82afde6682c570ddc21c
2
+ SHA256:
3
+ metadata.gz: 47a04414eade53832c4b900305ca3a034999724c0cabd6aceacb908192a6124f
4
+ data.tar.gz: 24c67d2cacbb5f64b5b7d63293c7fdbe143797d0102b732983fc78028469dfc9
5
5
  SHA512:
6
- metadata.gz: '0588bb0b62119753f79382bfe9955f7db54a693f2625c05426bcf08f131ed8b5b10fdb1e2bd0950545e030530ecfa823383c037747e654b43e7aa650db7187cb'
7
- data.tar.gz: 6365980a8eece62d0d092349ed583afb1a04e749577f994da5da004dfe4576b64c07edc8744680eecda8f9637d726e6c878a0d50cd281c322070adb67c36df37
6
+ metadata.gz: eb63ada090f884f750828b7c116d1066a020c87ab043d929e4ad46b035299c95972acf1d458813a34da797273e0656fc7613977cfef24c6e0765a7a8dece9a6a
7
+ data.tar.gz: 75314e320e2ed5f18e34c4038d467aef14e73f9b0e4fe01f61955369a52ee28e246e62662a94c3e1d1b9f7ea9999049f8d58e5f7af80479fc88a97b91055720e
@@ -1,6 +1,37 @@
1
1
  # Change log
2
2
 
3
- ## master
3
+ ## 0.7.0 (2020-01-07)
4
+
5
+ - Refactor AnyCable integration ([@palkan][])
6
+
7
+ Now you only need to set AnyCable broadcast adapter:
8
+
9
+ ```ruby
10
+ LiteCable.broadcast_adapter = :any_cable
11
+ ```
12
+
13
+ ```sh
14
+ # or via env/config
15
+ LITECABLE_BROADCAST_ADAPTER=any_cable ruby my_app.rb
16
+ ```
17
+
18
+ - Adapterize broadcast adapters ([@palkan][])
19
+
20
+ - Drop Ruby 2.4 support ([palkan][])
21
+
22
+ ## 0.6.0 (2019-04-12) 🚀
23
+
24
+ - Drop Ruby 2.3 support ([@palkan][])
25
+
26
+ ## 0.5.0 (2017-12-20)
27
+
28
+ - Upgrade for AnyCable 0.5.0 ([@palkan][])
29
+
30
+ ## 0.4.1 (2017-02-04)
31
+
32
+ - Use `websocket-ruby` with sub-protocols support ([@palkan][])
33
+
34
+ ## 0.4.0 (2017-01-29)
4
35
 
5
36
  - Initial version. ([@palkan][])
6
37
 
@@ -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,4 +1,5 @@
1
- [![Gem Version](https://badge.fury.io/rb/litecable.svg)](https://rubygems.org/gems/litecable) [![Build Status](https://travis-ci.org/anycable/litecable.svg?branch=master)](https://travis-ci.org/anycable/litecable) [![Circle CI](https://circleci.com/gh/anycable/litecable/tree/master.svg?style=svg)](https://circleci.com/gh/anycable/anycable/tree/master)
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)
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 Lite Cable Chat](https://github.com/palkan/litecable/tree/master/examples/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 'litecable'
26
+ gem "litecable"
24
27
  ```
25
28
 
26
- And then execute:
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 _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_.
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 '/cable' do
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, { 'Content-Type' => 'text/plain' }, ['OK']] }
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. You should write a simple server script:
81
+ Lite Cable is AnyCable-compatible out-of-the-box:
82
+
83
+ - Set broadcast adapter to AnyCable:
85
84
 
86
85
  ```ruby
87
- #!/usr/bin/env ruby
86
+ LiteCable.broadcast_adapter = :any_cable
87
+ ```
88
88
 
89
- require "my_app"
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
- # Turn AnyCable compatibility mode
94
- LiteCable.anycable!
91
+ - Configure connection factory:
95
92
 
96
- Anycable.configure do |config|
97
- config.connection_factory = MyApp::Connection
98
- end
93
+ ```ruby
94
+ AnyCable.connection_factory = MyApp::Connection
95
+ ```
99
96
 
100
- Anycable::Server.start
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
- 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.
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/anycable/litecable.
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](http://opensource.org/licenses/MIT).
128
-
130
+ The gem is available as open source under the terms of the [MIT License](./LICENSE.txt).
@@ -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,21 +1,15 @@
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)
18
- new(socket, **options)
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
@@ -50,13 +45,27 @@ module LiteCable
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,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module LiteCable
3
4
  # rubocop:disable Metrics/LineLength
4
5
  module Channel
@@ -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,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module LiteCable
3
4
  module Channel
4
5
  # Stores channels identifiers and corresponding classes.
@@ -10,6 +11,7 @@ module LiteCable
10
11
  class << self
11
12
  def add(id, channel_class)
12
13
  raise AlreadyRegisteredError if find(id)
14
+
13
15
  channels[id] = channel_class
14
16
  end
15
17
 
@@ -20,6 +22,7 @@ module LiteCable
20
22
  def find!(id)
21
23
  channel_class = find(id)
22
24
  raise UnknownChannelError unless channel_class
25
+
23
26
  channel_class
24
27
  end
25
28
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module LiteCable
3
4
  # rubocop:disable Metrics/LineLength
4
5
  module Channel
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module LiteCable
3
4
  module Coders # :nodoc:
4
5
  require "lite_cable/coders/raw"
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "json"
3
4
 
4
5
  module LiteCable
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module LiteCable
3
4
  module Coders
4
5
  # No-op coder
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
- require "anyway"
3
- require 'logger'
2
+
3
+ require "anyway_config"
4
+ require "logger"
4
5
 
5
6
  module LiteCable
6
- # Anycable configuration
7
+ # AnyCable configuration
7
8
  class Config < Anyway::Config
8
9
  require "lite_cable/coders/json"
9
10
  require "lite_cable/coders/raw"
@@ -11,8 +12,9 @@ module LiteCable
11
12
  config_name :litecable
12
13
 
13
14
  attr_config :logger,
14
- coder: Coders::JSON,
15
- identifier_coder: Coders::Raw,
16
- log_level: Logger::INFO
15
+ coder: Coders::JSON,
16
+ broadcast_adapter: :memory,
17
+ identifier_coder: Coders::Raw,
18
+ log_level: Logger::INFO
17
19
  end
18
20
  end