anycable 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -6
- data/CHANGELOG.md +10 -0
- data/MIT-LICENSE +1 -1
- data/README.md +6 -64
- data/anycable.gemspec +3 -3
- data/bin/console +1 -2
- data/lib/anycable/config.rb +2 -1
- data/lib/anycable/pubsub.rb +1 -0
- data/lib/anycable/rpc/rpc_services.rb +1 -3
- data/lib/anycable/rpc_handler.rb +53 -64
- data/lib/anycable/server.rb +0 -1
- data/lib/anycable/version.rb +1 -1
- data/lib/anycable.rb +25 -12
- data/protos/rpc.proto +1 -3
- metadata +21 -31
- data/gemfiles/rails5.gemfile +0 -6
- data/gemfiles/railsmaster.gemfile +0 -6
- data/lib/anycable/actioncable/channel.rb +0 -43
- data/lib/anycable/actioncable/connection.rb +0 -95
- data/lib/anycable/actioncable/server.rb +0 -14
- data/lib/anycable/refinements/subscriptions.rb +0 -14
- data/lib/generators/anycable/USAGE +0 -7
- data/lib/generators/anycable/anycable_generator.rb +0 -11
- data/lib/generators/anycable/templates/script +0 -8
- data/lib/tasks/anycable_tasks.rake +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2589605d172fda191b1733259d1205e474754285
|
4
|
+
data.tar.gz: 444266a714ada061f08f699ffafd61f08edd6e59
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cdcdca3db177557e4d144d0af7b8d8a643ad2dfe1c3728e7be95aaa84494e21f38e7bda57d61c3f617f62b1e7302be2c19a0b07b4e5795fb213b898bd8279280
|
7
|
+
data.tar.gz: 669cdc0c8b3d83114a1a0f5acf2e7a1686e70ba2a739a1acdcbdc01cdcbc5122e56eab907f26aefe49cf227a631a047f17a8d817c75acfa429d6654f9b9e00c8
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
|
+
## 0.4.0
|
4
|
+
|
5
|
+
- Refactor RPC API. ([@palkan][])
|
6
|
+
|
7
|
+
Replace `Subscribe`, `Unsubscribe` and `Perform` methods with `Command` method.
|
8
|
+
|
9
|
+
- Extract Rails functionality to separate gem. ([@palkan][])
|
10
|
+
|
11
|
+
All Rails specifics now live here https://github.com/anycable/anycable-rails.
|
12
|
+
|
3
13
|
## 0.3.0 (2016-12-28)
|
4
14
|
|
5
15
|
- Handle `Disconnect` requests. ([@palkan][])
|
data/MIT-LICENSE
CHANGED
data/README.md
CHANGED
@@ -3,25 +3,20 @@
|
|
3
3
|
|
4
4
|
# Anycable
|
5
5
|
|
6
|
-
AnyCable allows you to use any WebSocket server (written in any language) as a replacement for
|
6
|
+
AnyCable allows you to use any WebSocket server (written in any language) as a replacement for your Ruby server (such as Faye, ActionCable, etc).
|
7
7
|
|
8
|
-
|
8
|
+
AnyCable uses ActionCable protocol, so you can use ActionCable [JavaScript client](https://www.npmjs.com/package/actioncable) without any monkey-patching.
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
[Example Application](https://github.com/anycable/anycable_demo)
|
13
|
-
|
14
|
-
**NOTE**: MacOS users, please, beware of [Sierra-related bug](
|
15
|
-
https://github.com/grpc/grpc/issues/8403).
|
10
|
+
**NOTE**: Since version 0.4.0 this repository contains only core functionality and connot be used separately as is.
|
11
|
+
Rails plug-n-play integration has been extracted to [anycable-rails](https://github.com/anycable/anycable-rails) gem.
|
16
12
|
|
17
13
|
<a href="https://evilmartians.com/">
|
18
14
|
<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54"></a>
|
19
15
|
|
20
16
|
## Requirements
|
21
17
|
|
22
|
-
- Ruby ~> 2.3;
|
23
|
-
-
|
24
|
-
- Redis
|
18
|
+
- Ruby ~> 2.3, < 2.4 (follow [this issue](https://github.com/grpc/grpc/issues/9296) for Ruby 2.4 support);
|
19
|
+
- Redis (for brodcasting, [discuss other options](https://github.com/anycable/anycable/issues/2) with us!)
|
25
20
|
|
26
21
|
## How It Works?
|
27
22
|
|
@@ -39,62 +34,10 @@ https://github.com/grpc/grpc/issues/8403).
|
|
39
34
|
- [Anycable Go](https://github.com/anycable/anycable-go)
|
40
35
|
- [ErlyCable](https://github.com/anycable/erlycable)
|
41
36
|
|
42
|
-
|
43
|
-
## Installation
|
44
|
-
|
45
|
-
Add Anycable to your application's Gemfile:
|
46
|
-
|
47
|
-
```ruby
|
48
|
-
gem 'anycable', group: :production
|
49
|
-
```
|
50
|
-
|
51
|
-
And then run:
|
52
|
-
|
53
|
-
```shell
|
54
|
-
rails generate anycable
|
55
|
-
```
|
56
|
-
|
57
|
-
to create executable.
|
58
|
-
|
59
|
-
You can use _built-in_ ActionCable for test and development.
|
60
|
-
|
61
37
|
## Configuration
|
62
38
|
|
63
|
-
Add `config/anycable.yml`if you want to override defaults (see below):
|
64
|
-
|
65
|
-
```yml
|
66
|
-
production:
|
67
|
-
# gRPC server host
|
68
|
-
rpc_host: "localhost:50051"
|
69
|
-
# Redis URL (for broadcasting)
|
70
|
-
redis_url: "redis://localhost:6379/2"
|
71
|
-
# Redis channel name
|
72
|
-
redis_channel: "anycable"
|
73
|
-
|
74
|
-
```
|
75
|
-
|
76
39
|
Anycable uses [anyway_config](https://github.com/palkan/anyway_config), thus it is also possible to set configuration variables through `secrets.yml` or environment vars.
|
77
40
|
|
78
|
-
## Usage
|
79
|
-
|
80
|
-
Run Anycable RPC server:
|
81
|
-
|
82
|
-
```ruby
|
83
|
-
./bin/anycable
|
84
|
-
```
|
85
|
-
|
86
|
-
and also run AnyCable-compatible WebSocket server, e.g. [anycable-go](https://github.com/anycable/anycable-go):
|
87
|
-
|
88
|
-
```sh
|
89
|
-
anycable-go -addr='localhost:3334'
|
90
|
-
```
|
91
|
-
|
92
|
-
Don't forget to set cable url in your `config/environments/production.rb`:
|
93
|
-
|
94
|
-
```ruby
|
95
|
-
config.action_cable.url = "ws://localhost:3334/cable"
|
96
|
-
```
|
97
|
-
|
98
41
|
## ActionCable Compatibility
|
99
42
|
|
100
43
|
This is the compatibility list for the AnyCable gem, not for AnyCable servers (which may not support some of the features yet).
|
@@ -113,7 +56,6 @@ Streaming | +
|
|
113
56
|
[Custom stream callbacks](http://edgeapi.rubyonrails.org/classes/ActionCable/Channel/Streams.html) | -
|
114
57
|
Broadcasting | +
|
115
58
|
|
116
|
-
|
117
59
|
## Contributing
|
118
60
|
|
119
61
|
Bug reports and pull requests are welcome on GitHub at https://github.com/anycable/anycable.
|
data/anycable.gemspec
CHANGED
@@ -17,14 +17,14 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
|
-
spec.add_dependency "
|
21
|
-
spec.add_dependency "anyway_config", "~>0.4.0"
|
20
|
+
spec.add_dependency "anyway_config", "~>0.5.0"
|
22
21
|
spec.add_dependency "grpc", "~> 1.0"
|
23
22
|
spec.add_dependency "redis", "~> 3.0"
|
24
23
|
|
25
24
|
spec.add_development_dependency "bundler", "~> 1"
|
26
25
|
spec.add_development_dependency "rake", "~> 10.0"
|
27
|
-
spec.add_development_dependency "
|
26
|
+
spec.add_development_dependency "rack", "~> 2.0"
|
27
|
+
spec.add_development_dependency "rspec", ">= 3.5"
|
28
28
|
spec.add_development_dependency "simplecov", ">= 0.3.8"
|
29
29
|
spec.add_development_dependency "pry-byebug"
|
30
30
|
end
|
data/bin/console
CHANGED
data/lib/anycable/config.rb
CHANGED
@@ -6,7 +6,8 @@ module Anycable
|
|
6
6
|
class Config < Anyway::Config
|
7
7
|
config_name :anycable
|
8
8
|
|
9
|
-
attr_config
|
9
|
+
attr_config :connection_factory,
|
10
|
+
rpc_host: "localhost:50051",
|
10
11
|
redis_url: "redis://localhost:6379/5",
|
11
12
|
redis_channel: "anycable",
|
12
13
|
debug: false
|
data/lib/anycable/pubsub.rb
CHANGED
@@ -17,9 +17,7 @@ module Anycable
|
|
17
17
|
self.service_name = 'anycable.RPC'
|
18
18
|
|
19
19
|
rpc :Connect, ConnectionRequest, ConnectionResponse
|
20
|
-
rpc :
|
21
|
-
rpc :Unsubscribe, CommandMessage, CommandResponse
|
22
|
-
rpc :Perform, CommandMessage, CommandResponse
|
20
|
+
rpc :Command, CommandMessage, CommandResponse
|
23
21
|
rpc :Disconnect, DisconnectRequest, DisconnectResponse
|
24
22
|
end
|
25
23
|
|
data/lib/anycable/rpc_handler.rb
CHANGED
@@ -1,11 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require 'anycable/actioncable/connection'
|
3
|
-
require 'anycable/actioncable/channel'
|
4
2
|
require 'anycable/rpc/rpc'
|
5
3
|
require 'anycable/rpc/rpc_services'
|
6
4
|
|
7
5
|
# rubocop:disable Metrics/ClassLength
|
8
|
-
# rubocop:disable Metrics/AbcSize
|
9
6
|
# rubocop:disable Metrics/MethodLength
|
10
7
|
module Anycable
|
11
8
|
# RPC service handler
|
@@ -14,12 +11,7 @@ module Anycable
|
|
14
11
|
def connect(request, _unused_call)
|
15
12
|
logger.debug("RPC Connect: #{request}")
|
16
13
|
|
17
|
-
connection =
|
18
|
-
env:
|
19
|
-
path_env(request.path).merge(
|
20
|
-
'HTTP_COOKIE' => request.headers['Cookie']
|
21
|
-
)
|
22
|
-
)
|
14
|
+
connection = factory.create(env: rack_env(request))
|
23
15
|
|
24
16
|
connection.handle_open
|
25
17
|
|
@@ -28,7 +20,7 @@ module Anycable
|
|
28
20
|
else
|
29
21
|
Anycable::ConnectionResponse.new(
|
30
22
|
status: Anycable::Status::SUCCESS,
|
31
|
-
identifiers: connection.
|
23
|
+
identifiers: connection.identifiers_json,
|
32
24
|
transmissions: connection.transmissions
|
33
25
|
)
|
34
26
|
end
|
@@ -37,12 +29,9 @@ module Anycable
|
|
37
29
|
def disconnect(request, _unused_call)
|
38
30
|
logger.debug("RPC Disonnect: #{request}")
|
39
31
|
|
40
|
-
connection =
|
41
|
-
env:
|
42
|
-
|
43
|
-
'HTTP_COOKIE' => request.headers['Cookie']
|
44
|
-
),
|
45
|
-
identifiers_json: request.identifiers,
|
32
|
+
connection = factory.create(
|
33
|
+
env: rack_env(request),
|
34
|
+
identifiers: request.identifiers,
|
46
35
|
subscriptions: request.subscriptions
|
47
36
|
)
|
48
37
|
|
@@ -53,48 +42,39 @@ module Anycable
|
|
53
42
|
end
|
54
43
|
end
|
55
44
|
|
56
|
-
def
|
57
|
-
logger.debug("RPC
|
58
|
-
|
59
|
-
run_command(message)
|
60
|
-
channel.do_subscribe
|
61
|
-
if channel.subscription_rejected?
|
62
|
-
Anycable::CommandResponse.new(
|
63
|
-
status: Anycable::Status::ERROR,
|
64
|
-
disconnect: connection.closed?,
|
65
|
-
transmissions: connection.transmissions
|
66
|
-
)
|
67
|
-
else
|
68
|
-
Anycable::CommandResponse.new(
|
69
|
-
status: Anycable::Status::SUCCESS,
|
70
|
-
disconnect: connection.closed?,
|
71
|
-
stop_streams: channel.stop_streams?,
|
72
|
-
streams: channel.streams,
|
73
|
-
transmissions: connection.transmissions
|
74
|
-
)
|
75
|
-
end
|
76
|
-
end
|
45
|
+
def command(message, _unused_call)
|
46
|
+
logger.debug("RPC Command: #{message}")
|
47
|
+
|
48
|
+
run_command(message)
|
77
49
|
end
|
78
50
|
|
79
|
-
|
80
|
-
|
51
|
+
private
|
52
|
+
|
53
|
+
def run_command(message)
|
54
|
+
connection = factory.create(
|
55
|
+
identifiers: message.connection_identifiers
|
56
|
+
)
|
81
57
|
|
82
|
-
|
83
|
-
connection.subscriptions.remove_subscription(channel)
|
58
|
+
channel = connection.channel_for(message.identifier)
|
84
59
|
|
60
|
+
if !channel.nil?
|
61
|
+
send("handle_#{message.command}", message, connection, channel)
|
62
|
+
else
|
85
63
|
Anycable::CommandResponse.new(
|
86
|
-
status: Anycable::Status::
|
87
|
-
disconnect: false,
|
88
|
-
stop_streams: true
|
64
|
+
status: Anycable::Status::ERROR
|
89
65
|
)
|
90
66
|
end
|
91
67
|
end
|
92
68
|
|
93
|
-
def
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
69
|
+
def handle_subscribe(_msg, connection, channel)
|
70
|
+
channel.handle_subscribe
|
71
|
+
if channel.subscription_rejected?
|
72
|
+
Anycable::CommandResponse.new(
|
73
|
+
status: Anycable::Status::ERROR,
|
74
|
+
disconnect: connection.closed?,
|
75
|
+
transmissions: connection.transmissions
|
76
|
+
)
|
77
|
+
else
|
98
78
|
Anycable::CommandResponse.new(
|
99
79
|
status: Anycable::Status::SUCCESS,
|
100
80
|
disconnect: connection.closed?,
|
@@ -105,33 +85,38 @@ module Anycable
|
|
105
85
|
end
|
106
86
|
end
|
107
87
|
|
108
|
-
|
88
|
+
def handle_unsubscribe(_mgs, connection, channel)
|
89
|
+
channel.handle_unsubscribe
|
109
90
|
|
110
|
-
|
111
|
-
|
112
|
-
|
91
|
+
Anycable::CommandResponse.new(
|
92
|
+
status: Anycable::Status::SUCCESS,
|
93
|
+
disconnect: connection.closed?,
|
94
|
+
stop_streams: true,
|
95
|
+
transmissions: connection.transmissions
|
113
96
|
)
|
97
|
+
end
|
114
98
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
99
|
+
def handle_message(msg, connection, channel)
|
100
|
+
channel.handle_action(msg.data)
|
101
|
+
Anycable::CommandResponse.new(
|
102
|
+
status: Anycable::Status::SUCCESS,
|
103
|
+
disconnect: connection.closed?,
|
104
|
+
stop_streams: channel.stop_streams?,
|
105
|
+
streams: channel.streams,
|
106
|
+
transmissions: connection.transmissions
|
107
|
+
)
|
124
108
|
end
|
125
109
|
|
126
110
|
# Build env from path
|
127
|
-
def
|
128
|
-
uri = URI.parse(path)
|
111
|
+
def rack_env(request)
|
112
|
+
uri = URI.parse(request.path)
|
129
113
|
{
|
130
114
|
'QUERY_STRING' => uri.query,
|
131
115
|
'SCRIPT_NAME' => '',
|
132
116
|
'PATH_INFO' => uri.path,
|
133
117
|
'SERVER_PORT' => uri.port.to_s,
|
134
118
|
'HTTP_HOST' => uri.host,
|
119
|
+
'HTTP_COOKIE' => request.headers['Cookie'],
|
135
120
|
# Hack to avoid Missing rack.input error
|
136
121
|
'rack.request.form_input' => '',
|
137
122
|
'rack.input' => '',
|
@@ -142,5 +127,9 @@ module Anycable
|
|
142
127
|
def logger
|
143
128
|
Anycable.logger
|
144
129
|
end
|
130
|
+
|
131
|
+
def factory
|
132
|
+
Anycable.config.connection_factory
|
133
|
+
end
|
145
134
|
end
|
146
135
|
end
|
data/lib/anycable/server.rb
CHANGED
data/lib/anycable/version.rb
CHANGED
data/lib/anycable.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require "anycable/version"
|
3
3
|
require "anycable/config"
|
4
|
-
require "anycable/
|
4
|
+
require "anycable/server"
|
5
|
+
require "anycable/pubsub"
|
6
|
+
require "logger"
|
5
7
|
|
6
8
|
# Anycable allows to use any websocket service (written in any language) as a replacement
|
7
9
|
# for ActionCable server.
|
@@ -11,19 +13,30 @@ require "anycable/actioncable/server"
|
|
11
13
|
#
|
12
14
|
# Broadcasting messages to WS is done through Redis Pub/Sub.
|
13
15
|
module Anycable
|
14
|
-
|
15
|
-
|
16
|
-
|
16
|
+
class << self
|
17
|
+
def logger=(logger)
|
18
|
+
@logger = logger
|
19
|
+
end
|
17
20
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
+
def logger
|
22
|
+
@logger ||= Anycable.config.debug ? Logger.new(STDOUT) : Logger.new('/dev/null')
|
23
|
+
end
|
21
24
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
+
def config
|
26
|
+
@config ||= Config.new
|
27
|
+
end
|
28
|
+
|
29
|
+
def configure
|
30
|
+
yield(config) if block_given?
|
31
|
+
end
|
32
|
+
|
33
|
+
def pubsub
|
34
|
+
@pubsub ||= PubSub.new
|
35
|
+
end
|
25
36
|
|
26
|
-
|
27
|
-
|
37
|
+
# Broadcast message to the channel
|
38
|
+
def broadcast(channel, payload)
|
39
|
+
pubsub.broadcast(channel, payload)
|
40
|
+
end
|
28
41
|
end
|
29
42
|
end
|
data/protos/rpc.proto
CHANGED
@@ -4,9 +4,7 @@ package anycable;
|
|
4
4
|
|
5
5
|
service RPC {
|
6
6
|
rpc Connect (ConnectionRequest) returns (ConnectionResponse) {}
|
7
|
-
rpc
|
8
|
-
rpc Unsubscribe (CommandMessage) returns (CommandResponse) {}
|
9
|
-
rpc Perform (CommandMessage) returns (CommandResponse) {}
|
7
|
+
rpc Command (CommandMessage) returns (CommandResponse) {}
|
10
8
|
rpc Disconnect (DisconnectRequest) returns (DisconnectResponse) {}
|
11
9
|
}
|
12
10
|
|
metadata
CHANGED
@@ -1,43 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: anycable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- palkan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-01-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: rails
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '5'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '5'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: anyway_config
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
30
16
|
requirements:
|
31
17
|
- - "~>"
|
32
18
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.
|
19
|
+
version: 0.5.0
|
34
20
|
type: :runtime
|
35
21
|
prerelease: false
|
36
22
|
version_requirements: !ruby/object:Gem::Requirement
|
37
23
|
requirements:
|
38
24
|
- - "~>"
|
39
25
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0.
|
26
|
+
version: 0.5.0
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: grpc
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -95,19 +81,33 @@ dependencies:
|
|
95
81
|
- !ruby/object:Gem::Version
|
96
82
|
version: '10.0'
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
84
|
+
name: rack
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '2.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '2.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '3.
|
103
|
+
version: '3.5'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '3.
|
110
|
+
version: '3.5'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: simplecov
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -168,24 +168,14 @@ files:
|
|
168
168
|
- bin/console
|
169
169
|
- bin/setup
|
170
170
|
- circle.yml
|
171
|
-
- gemfiles/rails5.gemfile
|
172
|
-
- gemfiles/railsmaster.gemfile
|
173
171
|
- lib/anycable.rb
|
174
|
-
- lib/anycable/actioncable/channel.rb
|
175
|
-
- lib/anycable/actioncable/connection.rb
|
176
|
-
- lib/anycable/actioncable/server.rb
|
177
172
|
- lib/anycable/config.rb
|
178
173
|
- lib/anycable/pubsub.rb
|
179
|
-
- lib/anycable/refinements/subscriptions.rb
|
180
174
|
- lib/anycable/rpc/rpc.rb
|
181
175
|
- lib/anycable/rpc/rpc_services.rb
|
182
176
|
- lib/anycable/rpc_handler.rb
|
183
177
|
- lib/anycable/server.rb
|
184
178
|
- lib/anycable/version.rb
|
185
|
-
- lib/generators/anycable/USAGE
|
186
|
-
- lib/generators/anycable/anycable_generator.rb
|
187
|
-
- lib/generators/anycable/templates/script
|
188
|
-
- lib/tasks/anycable_tasks.rake
|
189
179
|
- protos/rpc.proto
|
190
180
|
homepage: http://github.com/anycable/anycable
|
191
181
|
licenses:
|
data/gemfiles/rails5.gemfile
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require "action_cable"
|
3
|
-
|
4
|
-
module ActionCable
|
5
|
-
module Channel
|
6
|
-
class Base # :nodoc:
|
7
|
-
alias do_subscribe subscribe_to_channel
|
8
|
-
|
9
|
-
public :do_subscribe, :subscription_rejected?
|
10
|
-
|
11
|
-
def subscribe_to_channel
|
12
|
-
# noop
|
13
|
-
end
|
14
|
-
|
15
|
-
attr_reader :stop_streams
|
16
|
-
|
17
|
-
def stream_from(broadcasting, callback = nil, coder: nil)
|
18
|
-
raise ArgumentError('Unsupported') if callback.present? || coder.present? || block_given?
|
19
|
-
streams << broadcasting
|
20
|
-
end
|
21
|
-
|
22
|
-
def stop_all_streams
|
23
|
-
@stop_streams = true
|
24
|
-
end
|
25
|
-
|
26
|
-
def streams
|
27
|
-
@streams ||= []
|
28
|
-
end
|
29
|
-
|
30
|
-
def stop_streams?
|
31
|
-
stop_streams == true
|
32
|
-
end
|
33
|
-
|
34
|
-
def delegate_connection_identifiers
|
35
|
-
connection.identifiers.each do |identifier|
|
36
|
-
define_singleton_method(identifier) do
|
37
|
-
connection.fetch_identifier(identifier)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
@@ -1,95 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require "action_cable"
|
3
|
-
require "anycable/refinements/subscriptions"
|
4
|
-
|
5
|
-
module ActionCable
|
6
|
-
module Connection
|
7
|
-
class Base # :nodoc:
|
8
|
-
using Anycable::Refinements::Subscriptions
|
9
|
-
|
10
|
-
attr_reader :transmissions
|
11
|
-
|
12
|
-
class << self
|
13
|
-
def identified_by(*identifiers)
|
14
|
-
super
|
15
|
-
Array(identifiers).each do |identifier|
|
16
|
-
define_method(identifier) do
|
17
|
-
instance_variable_get(:"@#{identifier}") || fetch_identifier(identifier)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def initialize(env: {}, identifiers_json: '{}', subscriptions: [])
|
24
|
-
@ids = ActiveSupport::JSON.decode(identifiers_json)
|
25
|
-
|
26
|
-
@cached_ids = {}
|
27
|
-
@env = env
|
28
|
-
@coder = ActiveSupport::JSON
|
29
|
-
@closed = false
|
30
|
-
@transmissions = []
|
31
|
-
@subscriptions = ActionCable::Connection::Subscriptions.new(self)
|
32
|
-
|
33
|
-
# Initialize channels if any
|
34
|
-
subscriptions.each { |id| @subscriptions.fetch(id) }
|
35
|
-
end
|
36
|
-
|
37
|
-
# Create a channel instance from identifier for the connection
|
38
|
-
def channel_for(identifier)
|
39
|
-
subscriptions.fetch(identifier)
|
40
|
-
end
|
41
|
-
|
42
|
-
def handle_open
|
43
|
-
connect if respond_to?(:connect)
|
44
|
-
send_welcome_message
|
45
|
-
rescue ActionCable::Connection::Authorization::UnauthorizedError
|
46
|
-
close
|
47
|
-
end
|
48
|
-
|
49
|
-
def handle_close
|
50
|
-
subscriptions.unsubscribe_from_all
|
51
|
-
disconnect if respond_to?(:disconnect)
|
52
|
-
end
|
53
|
-
|
54
|
-
def close
|
55
|
-
@closed = true
|
56
|
-
end
|
57
|
-
|
58
|
-
def closed?
|
59
|
-
@closed
|
60
|
-
end
|
61
|
-
|
62
|
-
def transmit(cable_message)
|
63
|
-
transmissions << encode(cable_message)
|
64
|
-
end
|
65
|
-
|
66
|
-
def dispose
|
67
|
-
@closed = false
|
68
|
-
transmissions.clear
|
69
|
-
end
|
70
|
-
|
71
|
-
# Generate identifiers info.
|
72
|
-
# Converts GlobalID compatible vars to corresponding global IDs params.
|
73
|
-
def identifiers_hash
|
74
|
-
identifiers.each_with_object({}) do |id, acc|
|
75
|
-
obj = instance_variable_get("@#{id}")
|
76
|
-
next unless obj
|
77
|
-
acc[id] = obj.try(:to_gid_param) || obj
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
# Fetch identifier and deserialize if neccessary
|
82
|
-
def fetch_identifier(name)
|
83
|
-
@cached_ids[name] ||= @cached_ids.fetch(name) do
|
84
|
-
val = @ids[name.to_s]
|
85
|
-
next val unless val.is_a?(String)
|
86
|
-
GlobalID::Locator.locate(val) || val
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
def logger
|
91
|
-
::Rails.logger
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module Anycable
|
3
|
-
module Refinements
|
4
|
-
module Subscriptions # :nodoc:
|
5
|
-
refine ActionCable::Connection::Subscriptions do
|
6
|
-
# Find or add a subscription to the list
|
7
|
-
def fetch(identifier)
|
8
|
-
add("identifier" => identifier) unless subscriptions[identifier]
|
9
|
-
subscriptions[identifier]
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
@@ -1,11 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require "rails/generators/base"
|
3
|
-
|
4
|
-
class AnycableGenerator < Rails::Generators::Base # :nodoc:
|
5
|
-
source_root File.expand_path('../templates', __FILE__)
|
6
|
-
|
7
|
-
def create_executable_file
|
8
|
-
template "script", "bin/anycable"
|
9
|
-
chmod "bin/anycable", 0o755
|
10
|
-
end
|
11
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
namespace :anycable do
|
3
|
-
desc "Make test gRPC call"
|
4
|
-
task check: :environment do
|
5
|
-
require 'grpc'
|
6
|
-
require 'anycable/rpc/rpc_services'
|
7
|
-
|
8
|
-
Anycable.logger = Logger.new(STDOUT)
|
9
|
-
stub = Anycable::RPC::Stub.new(Anycable.config.rpc_host, :this_channel_is_insecure)
|
10
|
-
stub.connect(
|
11
|
-
Anycable::ConnectionRequest.new(
|
12
|
-
path: 'http://example.com',
|
13
|
-
headers: { 'Cookie' => 'test=1;' }
|
14
|
-
)
|
15
|
-
)
|
16
|
-
end
|
17
|
-
end
|