anycable-core 1.2.1 → 1.2.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5f387a5b5a0a7535f698339c719f4f7f8debd3c799f5e69b7b54b46b599d3830
4
- data.tar.gz: 558f452d571cd33557836861083539fa130c266d5ded16764f0137a9494c39d2
3
+ metadata.gz: 43353c30169b14234846a634a2f6e2cf9b8c205725752fcc9de78ed088e2432a
4
+ data.tar.gz: aa0b65f611dd8598b230d152f4b51ddfbdbd92c020081d957ab3f18179c6623f
5
5
  SHA512:
6
- metadata.gz: 819b9da9e51dae8e6feca6be71550c72e3aaee4358e8245c95235a030f9ee130d3b49d48590eb3d4abc8275a7918c71130b48fd63e3b4b9a5fd46d34520942c7
7
- data.tar.gz: c3409d81a2b9c66593384de64d0cc66ac1c31d915d58a836af1c222438d152f18ca86830a86c7867b784ba2159aa80787a5abd5ea3b50d8edd99b835d572bbe8
6
+ metadata.gz: 6fc3a9531075ec9da6ba4c7dc0e2e00f863829930f80a8b794e40aad13215db134c6195619d272188032502c6ae123f3567d781168580e1eb718d200042910b3
7
+ data.tar.gz: b7d91672f1976952a40315d92956f0d5970947e89d85e6e94a31240e3428e63c56093c173236ef46f25f5da47d5030cfd5576cdce8c248600a9959ceaa5e8145
data/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.2.4 (2022-08-10)
6
+
7
+ - Add NATS pub/sub adapter. ([@palkan][])
8
+
9
+ - Setting the redis adapter to use the ruby driver. ([@smasry][])
10
+
11
+ ## 1.2.3 (2022-04-20)
12
+
13
+ - Pass unique connection id (_session id_) in the `anycable.sid` Rack env field. ([@palkan][])
14
+
15
+ ## 1.2.2 (2022-03-04)
16
+
17
+ - Allow Ruby 2.6.
18
+
5
19
  ## 1.2.1 (2022-02-21)
6
20
 
7
21
  - Fix RBS signature. ([@palkan][])
@@ -116,3 +130,4 @@ See [Changelog](https://github.com/anycable/anycable/blob/0-6-stable/CHANGELOG.m
116
130
  [@palkan]: https://github.com/palkan
117
131
  [@sponomarev]: https://github.com/sponomarev
118
132
  [@bibendi]: https://github.com/bibendi
133
+ [@smasry]: https://github.com/smasry
@@ -10,7 +10,7 @@ module AnyCable
10
10
  #
11
11
  # Example:
12
12
  #
13
- # AnyCable.broadast_adapter = :http
13
+ # AnyCable.broadcast_adapter = :http
14
14
  #
15
15
  # It uses configuration from global AnyCable config
16
16
  # by default.
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require "nats/client"
5
+ rescue LoadError
6
+ raise "Please, install the nats-pure gem to use NATS broadcast adapter"
7
+ end
8
+
9
+ require "json"
10
+
11
+ module AnyCable
12
+ module BroadcastAdapters
13
+ # NATS adapter for broadcasting.
14
+ #
15
+ # Example:
16
+ #
17
+ # AnyCable.broadcast_adapter = :nats
18
+ #
19
+ # It uses NATS configuration from global AnyCable config
20
+ # by default.
21
+ #
22
+ # You can override these params:
23
+ #
24
+ # AnyCable.broadcast_adapter = :nats, servers: "nats://my_nats:4242", channel: "_any_cable_"
25
+ class Nats < Base
26
+ attr_reader :nats_conn, :channel
27
+
28
+ def initialize(
29
+ channel: AnyCable.config.nats_channel,
30
+ **options
31
+ )
32
+ options = AnyCable.config.to_nats_params.merge(options)
33
+ @nats_conn = ::NATS.connect(nil, options)
34
+ @channel = channel
35
+ end
36
+
37
+ def raw_broadcast(payload)
38
+ nats_conn.publish(channel, payload)
39
+ end
40
+
41
+ def announce!
42
+ logger.info "Broadcasting NATS channel: #{channel}"
43
+ end
44
+ end
45
+ end
46
+ end
@@ -3,7 +3,7 @@
3
3
  begin
4
4
  require "redis"
5
5
  rescue LoadError
6
- raise "Please, install redis gem to use Redis broadcast adapter"
6
+ raise "Please, install the redis gem to use Redis broadcast adapter"
7
7
  end
8
8
 
9
9
  require "json"
@@ -14,7 +14,7 @@ module AnyCable
14
14
  #
15
15
  # Example:
16
16
  #
17
- # AnyCable.broadast_adapter = :redis
17
+ # AnyCable.broadcast_adapter = :redis
18
18
  #
19
19
  # It uses Redis configuration from global AnyCable config
20
20
  # by default.
@@ -30,6 +30,7 @@ module AnyCable
30
30
  **options
31
31
  )
32
32
  options = AnyCable.config.to_redis_params.merge(options)
33
+ options[:driver] = :ruby
33
34
  @redis_conn = ::Redis.new(**options)
34
35
  @channel = channel
35
36
  end
data/lib/anycable/cli.rb CHANGED
@@ -65,6 +65,8 @@ module AnyCable
65
65
 
66
66
  check_version!
67
67
 
68
+ configure_middleware!
69
+
68
70
  @server = AnyCable.server_builder.call(config)
69
71
 
70
72
  # Make sure middlewares are not adding after server has started
@@ -119,7 +121,7 @@ module AnyCable
119
121
  def wait_till_terminated
120
122
  self_read = setup_signals
121
123
 
122
- while readable_io = IO.select([self_read]) # rubocop:disable Lint/AssignmentInCondition,Lint/IncompatibleIoSelectWithFiberScheduler
124
+ while readable_io = IO.select([self_read]) # rubocop:disable Lint/AssignmentInCondition
123
125
  signal = readable_io.first[0].gets.strip
124
126
  raise Interrupt, "SIG#{signal} received"
125
127
  end
@@ -265,6 +267,12 @@ module AnyCable
265
267
  )
266
268
  end
267
269
 
270
+ def configure_middleware!
271
+ if config.sid_header_enabled?
272
+ AnyCable.middleware.use(AnyCable::Middlewares::EnvSid)
273
+ end
274
+ end
275
+
268
276
  def parse_gem_options!(args)
269
277
  config.parse_options!(args)
270
278
  rescue OptionParser::InvalidOption => e
@@ -29,6 +29,12 @@ module AnyCable
29
29
  redis_sentinels: nil,
30
30
  redis_channel: "__anycable__",
31
31
 
32
+ ### NATS options
33
+ nats_servers: "nats://localhost:4222",
34
+ nats_channel: "__anycable__",
35
+ nats_dont_randomize_servers: false,
36
+ nats_options: {},
37
+
32
38
  ### HTTP broadcasting options
33
39
  http_broadcast_url: "http://localhost:8090/_broadcast",
34
40
  http_broadcast_secret: nil,
@@ -43,14 +49,22 @@ module AnyCable
43
49
  http_health_path: "/health",
44
50
 
45
51
  ### Misc options
46
- version_check_enabled: true
52
+ version_check_enabled: true,
53
+ sid_header_enabled: true
47
54
  )
48
55
 
49
56
  if respond_to?(:coerce_types)
50
- coerce_types redis_sentinels: {type: nil, array: true}, debug: :boolean, version_check_enabled: :boolean
57
+ coerce_types(
58
+ redis_sentinels: {type: nil, array: true},
59
+ nats_servers: {type: nil, array: true},
60
+ nats_dont_randomize_servers: :boolean,
61
+ debug: :boolean,
62
+ version_check_enabled: :boolean
63
+ )
51
64
  end
52
65
 
53
- flag_options :debug
66
+ flag_options :debug, :nats_dont_randomize_servers
67
+ ignore_options :nats_options
54
68
 
55
69
  on_load do
56
70
  # @type self : AnyCable::Config
@@ -81,6 +95,11 @@ module AnyCable
81
95
  --redis-channel=name Redis channel for broadcasting, default: "__anycable__"
82
96
  --redis-sentinels=<...hosts> Redis Sentinel followers addresses (as a comma-separated list), default: nil
83
97
 
98
+ NATS PUB/SUB
99
+ --nats-servers=<...addresses> NATS servers for pub/sub, default: "nats://localhost:4222"
100
+ --nats-channel=name NATS channel for broadcasting, default: "__anycable__"
101
+ --nats-dont-randomize-servers Pass this option to disable NATS servers randomization during (re-)connect
102
+
84
103
  HTTP PUB/SUB
85
104
  --http-broadcast-url HTTP pub/sub endpoint URL, default: "http://localhost:8090/_broadcast"
86
105
  --http-broadcast-secret HTTP pub/sub authorization secret, default: <none> (disabled)
@@ -106,6 +125,14 @@ module AnyCable
106
125
  end
107
126
  end
108
127
 
128
+ # Build options for NATS.connect
129
+ def to_nats_params
130
+ {
131
+ servers: Array(nats_servers),
132
+ dont_randomize_servers: nats_dont_randomize_servers
133
+ }.merge(nats_options)
134
+ end
135
+
109
136
  # Build HTTP health server parameters
110
137
  def to_http_health_params
111
138
  {
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AnyCable
4
+ module Middlewares
5
+ # Set sid for request.env from metadata
6
+ class EnvSid < AnyCable::Middleware
7
+ def call(_method, request, meta)
8
+ return yield unless meta["sid"]
9
+ request.env.sid = meta["sid"]
10
+
11
+ yield
12
+ end
13
+ end
14
+ end
15
+ end
data/lib/anycable/rpc.rb CHANGED
@@ -88,4 +88,11 @@ module AnyCable
88
88
  class DisconnectResponse
89
89
  include StatusPredicates
90
90
  end
91
+
92
+ # TODO: Move sid to env in the future version of RPC proto
93
+ unless Env.instance_methods(false).include?(:sid)
94
+ class Env
95
+ attr_accessor :sid
96
+ end
97
+ end
91
98
  end
@@ -129,7 +129,8 @@ module AnyCable
129
129
  "rack.url_scheme" => uri.scheme&.sub(/^ws/, "http"),
130
130
  # AnyCable specific fields
131
131
  "anycable.raw_cstate" => request_env.cstate&.to_h,
132
- "anycable.raw_istate" => request_env.istate&.to_h
132
+ "anycable.raw_istate" => request_env.istate&.to_h,
133
+ "anycable.sid" => request_env.sid
133
134
  }.delete_if { |_k, v| v.nil? })
134
135
 
135
136
  env.merge!(build_headers(headers))
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AnyCable
4
- VERSION = "1.2.1"
4
+ VERSION = "1.2.4"
5
5
  end
data/lib/anycable.rb CHANGED
@@ -10,6 +10,7 @@ require "anycable/broadcast_adapters"
10
10
  require "anycable/middleware_chain"
11
11
  require "anycable/middlewares/exceptions"
12
12
  require "anycable/middlewares/check_version"
13
+ require "anycable/middlewares/env_sid"
13
14
 
14
15
  require "anycable/socket"
15
16
  require "anycable/rpc"
@@ -0,0 +1,10 @@
1
+ module AnyCable
2
+ module BroadcastAdapters
3
+ class Nats < Base
4
+ attr_reader nats_conn: untyped
5
+ attr_reader channel: String
6
+
7
+ def initialize: (?channel: String channel, **untyped options) -> void
8
+ end
9
+ end
10
+ end
@@ -8,6 +8,14 @@ module AnyCable
8
8
  def redis_sentinels=: (Array[String]) -> void
9
9
  def redis_channel: () -> String
10
10
  def redis_channel=: (String) -> void
11
+ def nats_servers: () -> Array[String]
12
+ def nats_servers=: (Array[String]) -> void
13
+ def nats_channel: () -> String
14
+ def nats_channel=: (String) -> void
15
+ def nats_dont_randomize_servers: () -> bool
16
+ def nats_dont_randomize_servers=: (bool) -> void
17
+ def nats_options: () -> Hash[untyped, untyped]
18
+ def nats_options=: (Hash[untyped, untyped]) -> void
11
19
  def http_broadcast_url: () -> String
12
20
  def http_broadcast_url=: (String) -> void
13
21
  def http_broadcast_secret: () -> String?
@@ -38,6 +46,7 @@ module AnyCable
38
46
  def http_health_port_provided?: () -> bool
39
47
  def to_redis_params: () -> { url: String, sentinels: Array[untyped]?, ssl_params: Hash[Symbol, untyped]? }
40
48
  def to_http_health_params: () -> { port: Integer?, path: String }
49
+ def to_nats_params: () -> Hash[Symbol, untyped]
41
50
 
42
51
  private
43
52
 
@@ -0,0 +1,6 @@
1
+ module AnyCable
2
+ module Middlewares
3
+ class EnvSid < AnyCable::Middleware
4
+ end
5
+ end
6
+ end
data/sig/anycable/rpc.rbs CHANGED
@@ -24,6 +24,7 @@ module AnyCable
24
24
 
25
25
  attr_accessor url: String
26
26
  attr_accessor headers: protoMap
27
+ attr_accessor sid: String?
27
28
 
28
29
  def initialize: (?url: String, ?headers: protoMap, ?cstate: protoMap?, ?istate: protoMap?) -> void
29
30
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: anycable-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - palkan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-21 00:00:00.000000000 Z
11
+ date: 2022-08-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: anyway_config
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '4.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: nats-pure
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: bundler
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -157,6 +171,7 @@ files:
157
171
  - lib/anycable/broadcast_adapters.rb
158
172
  - lib/anycable/broadcast_adapters/base.rb
159
173
  - lib/anycable/broadcast_adapters/http.rb
174
+ - lib/anycable/broadcast_adapters/nats.rb
160
175
  - lib/anycable/broadcast_adapters/redis.rb
161
176
  - lib/anycable/cli.rb
162
177
  - lib/anycable/config.rb
@@ -170,6 +185,7 @@ files:
170
185
  - lib/anycable/middleware.rb
171
186
  - lib/anycable/middleware_chain.rb
172
187
  - lib/anycable/middlewares/check_version.rb
188
+ - lib/anycable/middlewares/env_sid.rb
173
189
  - lib/anycable/middlewares/exceptions.rb
174
190
  - lib/anycable/protos/rpc_pb.rb
175
191
  - lib/anycable/rpc.rb
@@ -185,6 +201,7 @@ files:
185
201
  - sig/anycable/broadcast_adapters.rbs
186
202
  - sig/anycable/broadcast_adapters/base.rbs
187
203
  - sig/anycable/broadcast_adapters/http.rbs
204
+ - sig/anycable/broadcast_adapters/nats.rbs
188
205
  - sig/anycable/broadcast_adapters/redis.rbs
189
206
  - sig/anycable/cli.rbs
190
207
  - sig/anycable/config.rbs
@@ -197,6 +214,7 @@ files:
197
214
  - sig/anycable/middleware.rbs
198
215
  - sig/anycable/middleware_chain.rbs
199
216
  - sig/anycable/middlewares/check_version.rbs
217
+ - sig/anycable/middlewares/env_sid.rbs
200
218
  - sig/anycable/middlewares/exceptions.rbs
201
219
  - sig/anycable/rpc.rbs
202
220
  - sig/anycable/rpc/handler.rbs
@@ -223,14 +241,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
223
241
  requirements:
224
242
  - - ">="
225
243
  - !ruby/object:Gem::Version
226
- version: 2.7.0
244
+ version: 2.6.0
227
245
  required_rubygems_version: !ruby/object:Gem::Requirement
228
246
  requirements:
229
247
  - - ">="
230
248
  - !ruby/object:Gem::Version
231
249
  version: '0'
232
250
  requirements: []
233
- rubygems_version: 3.2.22
251
+ rubygems_version: 3.3.11
234
252
  signing_key:
235
253
  specification_version: 4
236
254
  summary: AnyCable core RPC implementation