anycable-core 1.2.5 → 1.3.0

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: 5e9ba8037b7cbd766d021b4e88d49101b6dc3e9a5a6b355929bf9aaa8494f33a
4
- data.tar.gz: 71cd40b2380601f322a335d774cfb41e39f8de6ac29f4b5201a825119bff1031
3
+ metadata.gz: 215d37d67fe10f536e6eb2a9b8ae5e53603d4653fb2034aff9abece234da7097
4
+ data.tar.gz: 50457dfd126925e875f3bb1ab323df90a0381f13de399f07e20a8cd4f2cab5d7
5
5
  SHA512:
6
- metadata.gz: f1a372e6d70eb1db64054aeafcc3baccd674d679652309526fbcfe9329799383b671d532cd16a52dd53b00b4a1658100d000f4564f2cbaac00502e02da00b668
7
- data.tar.gz: 5d9434268c8d7b3903544ab357caadcb69150be82d921c2de2916f4191b1280c0c3b981de285425d969bd1693b02974be4a844447576e3975ed0280c877be3c0
6
+ metadata.gz: 43eac0f870ba33726095d8801772d3b18dd2a909a937c9c03177aab163d2ee93f92979bcfcf4cb3eb2039e80e3f28ec123d9e215ee07fe4b87fb152510f7b87d
7
+ data.tar.gz: be1a5de79d480aa5d0b081354103f325cb3f997d8d134ba325b92d233408696236afedd600c7133ccb307ac7ceb9b16c60e284588942aa83886007384002a372
data/CHANGELOG.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.3.0 (2023-02-28)
6
+
7
+ - Add configuration presets. ([@palkan][])
8
+
9
+ Provide sensible defaults matching current platform (e.g., Fly.io).
10
+
11
+ - Require Ruby 2.7+ and Anyway Config 2.2+.
12
+
13
+ - Add `rpc_max_connection_age` option (if favour of `rpc_server_args.max_connection_age_ms`) and configured its **default value to be 300 (5 minutes)**. ([@palkan][])
14
+
15
+ - (_Experimental_) Add support for [grpc_kit](https://github.com/cookpad/grpc_kit) as an alternative gRPC implementation. ([@palkan][], [@cylon-v][])
16
+
17
+ Add `grpc_kit` to your Gemfile and specify `ANYCABLE_GRPC_IMPL=grpc_kit` env var to use it.
18
+
19
+ - Setting the redis driver to ruby specified. ([@smasry][])
20
+
21
+ - Add mutual TLS support for connections to Redis. ([@Envek][])
22
+
23
+ `ANYCABLE_REDIS_TLS_CLIENT_CERT_PATH` and `ANYCABLE_REDIS_TLS_CLIENT_KEY_PATH` settings to specify client certificate and key when connecting to Redis server that requires clients to authenticate themselves.
24
+
5
25
  ## 1.2.5 (2022-12-01)
6
26
 
7
27
  - Add `ANYCABLE_REDIS_TLS_VERIFY` setting to disable validation of Redis server TLS certificate. ([@Envek][])
@@ -132,7 +152,6 @@ See [#71](https://github.com/anycable/anycable/pull/71).
132
152
  See [Changelog](https://github.com/anycable/anycable/blob/0-6-stable/CHANGELOG.md) for versions <1.0.0.
133
153
 
134
154
  [@palkan]: https://github.com/palkan
135
- [@sponomarev]: https://github.com/sponomarev
136
- [@bibendi]: https://github.com/bibendi
137
155
  [@smasry]: https://github.com/smasry
138
156
  [@Envek]: https://github.com/Envek
157
+ [@cylon-v]: https://github.com/cylon-v
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2017-2022 Vladimir Dementyev
1
+ Copyright 2017-2023 Vladimir Dementyev
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/anycable.svg)](https://rubygems.org/gems/anycable)
2
2
  [![Build](https://github.com/anycable/anycable/workflows/Build/badge.svg)](https://github.com/anycable/anycable/actions)
3
+ [![Coverage Status](https://coveralls.io/repos/github/anycable/anycable/badge.svg?branch=master)](https://coveralls.io/github/anycable/anycable?branch=master)
3
4
  [![Documentation](https://img.shields.io/badge/docs-link-brightgreen.svg)](https://docs.anycable.io/v1)
4
5
 
5
6
  # AnyCable
@@ -18,8 +19,8 @@ AnyCable uses the same protocol as ActionCable, so you can use its [JavaScript c
18
19
 
19
20
  ## Requirements
20
21
 
21
- - Ruby >= 2.6
22
- - Redis (for broadcasting **in production**, [discuss other options](https://github.com/anycable/anycable/issues/2) with us!)
22
+ - Ruby >= 2.7
23
+ - Redis or NATS (for broadcasting **in production**, [discuss other options](https://github.com/anycable/anycable/issues/2) with us!)
23
24
 
24
25
  ## Usage
25
26
 
@@ -30,7 +30,7 @@ module AnyCable
30
30
  **options
31
31
  )
32
32
  options = AnyCable.config.to_redis_params.merge(options)
33
- options[:driver] = :ruby
33
+ options[:driver] ||= :ruby
34
34
  @redis_conn = ::Redis.new(**options)
35
35
  @channel = channel
36
36
  end
@@ -3,7 +3,7 @@
3
3
  require "anycable/broadcast_adapters/base"
4
4
 
5
5
  module AnyCable
6
- module BroadcastAdapters # :nodoc:
6
+ module BroadcastAdapters
7
7
  module_function
8
8
 
9
9
  def lookup_adapter(args)
data/lib/anycable/cli.rb CHANGED
@@ -333,7 +333,7 @@ module AnyCable
333
333
  $ anycable [options]
334
334
 
335
335
  CLI
336
- -r, --require=path Location of application file to require, default: "config/environment.rb"
336
+ -r, --require=path Location of application file to require, default candidates: #{APP_CANDIDATES.join(", ")}
337
337
  --server-command=command Command to run WebSocket server
338
338
  -v, --version Print version and exit
339
339
  -h, --help Show this help
@@ -21,6 +21,8 @@ module AnyCable
21
21
  config_name :anycable
22
22
 
23
23
  attr_config(
24
+ presets: "",
25
+
24
26
  ## PubSub
25
27
  broadcast_adapter: :redis,
26
28
 
@@ -29,6 +31,8 @@ module AnyCable
29
31
  redis_sentinels: nil,
30
32
  redis_channel: "__anycable__",
31
33
  redis_tls_verify: false,
34
+ redis_tls_client_cert_path: nil,
35
+ redis_tls_client_key_path: nil,
32
36
 
33
37
  ### NATS options
34
38
  nats_servers: "nats://localhost:4222",
@@ -54,23 +58,21 @@ module AnyCable
54
58
  sid_header_enabled: true
55
59
  )
56
60
 
57
- if respond_to?(:coerce_types)
58
- coerce_types(
59
- redis_sentinels: {type: nil, array: true},
60
- nats_servers: {type: nil, array: true},
61
- redis_tls_verify: :boolean,
62
- nats_dont_randomize_servers: :boolean,
63
- debug: :boolean,
64
- version_check_enabled: :boolean
65
- )
66
- end
61
+ coerce_types(
62
+ presets: {type: nil, array: true},
63
+ redis_sentinels: {type: nil, array: true},
64
+ nats_servers: {type: nil, array: true},
65
+ redis_tls_verify: :boolean,
66
+ nats_dont_randomize_servers: :boolean,
67
+ debug: :boolean,
68
+ version_check_enabled: :boolean
69
+ )
67
70
 
68
71
  flag_options :debug, :nats_dont_randomize_servers
69
72
  ignore_options :nats_options
70
73
 
71
- on_load do
72
- # @type self : AnyCable::Config
73
- self.debug = debug != false
74
+ def load(*)
75
+ super.tap { load_presets }
74
76
  end
75
77
 
76
78
  def log_level
@@ -97,6 +99,8 @@ module AnyCable
97
99
  --redis-channel=name Redis channel for broadcasting, default: "__anycable__"
98
100
  --redis-sentinels=<...hosts> Redis Sentinel followers addresses (as a comma-separated list), default: nil
99
101
  --redis-tls-verify=yes|no Whether to perform server certificate check in case of rediss:// protocol. Default: yes
102
+ --redis-tls-client_cert-path=path Default: nil
103
+ --redis-tls-client_key-path=path Default: nil
100
104
 
101
105
  NATS PUB/SUB
102
106
  --nats-servers=<...addresses> NATS servers for pub/sub, default: "nats://localhost:4222"
@@ -122,9 +126,23 @@ module AnyCable
122
126
 
123
127
  params[:sentinels] = sentinels.map { |sentinel| parse_sentinel(sentinel) }
124
128
  end.tap do |params|
125
- next unless redis_url.match?(/rediss:\/\//) && !redis_tls_verify?
126
-
127
- params[:ssl_params] = {verify_mode: OpenSSL::SSL::VERIFY_NONE}
129
+ next unless redis_url.match?(/rediss:\/\//)
130
+
131
+ if !!redis_tls_client_cert_path ^ !!redis_tls_client_key_path
132
+ raise_validation_error "Both Redis TLS client certificate and private key must be specified (or none of them)"
133
+ end
134
+
135
+ if !redis_tls_verify?
136
+ params[:ssl_params] = {verify_mode: OpenSSL::SSL::VERIFY_NONE}
137
+ else
138
+ cert_path, key_path = redis_tls_client_cert_path, redis_tls_client_key_path
139
+ if cert_path && key_path
140
+ params[:ssl_params] = {
141
+ cert: OpenSSL::X509::Certificate.new(File.read(cert_path)),
142
+ key: OpenSSL::PKey.read(File.read(key_path))
143
+ }
144
+ end
145
+ end
128
146
  end
129
147
  end
130
148
 
@@ -155,5 +173,42 @@ module AnyCable
155
173
  opts[:password] = uri.password if uri.password
156
174
  end
157
175
  end
176
+
177
+ def load_presets
178
+ if presets.nil? || presets.empty?
179
+ self.presets = detect_presets
180
+ __trace__&.record_value(presets, :presets, type: :env)
181
+ end
182
+
183
+ return if presets.empty?
184
+
185
+ presets.each { send(:"load_#{_1}_presets") if respond_to?(:"load_#{_1}_presets", true) }
186
+ end
187
+
188
+ def detect_presets
189
+ [].tap do
190
+ _1 << "fly" if ENV.key?("FLY_APP_NAME") && ENV.key?("FLY_ALLOC_ID") && ENV.key?("FLY_REGION")
191
+ end
192
+ end
193
+
194
+ def load_fly_presets
195
+ write_preset(:rpc_host, "0.0.0.0:50051", preset: "fly")
196
+
197
+ ws_app_name = ENV["ANYCABLE_FLY_WS_APP_NAME"]
198
+ return unless ws_app_name
199
+
200
+ region = ENV.fetch("FLY_REGION")
201
+
202
+ write_preset(:http_broadcast_url, "http://#{region}.#{ws_app_name}.internal:8090/_broadcast", preset: "fly")
203
+ write_preset(:nats_servers, "nats://#{region}.#{ws_app_name}.internal:4222", preset: "fly")
204
+ end
205
+
206
+ def write_preset(key, value, preset:)
207
+ # do not override explicitly provided values
208
+ return unless __trace__&.dig(key.to_s)&.source&.dig(:type) == :defaults
209
+
210
+ write_config_attr(key, value)
211
+ __trace__&.record_value(value, key, type: :preset, preset: preset)
212
+ end
158
213
  end
159
214
  end
@@ -3,13 +3,12 @@
3
3
  AnyCable::Config.attr_config(
4
4
  ### gRPC options
5
5
  rpc_host: "127.0.0.1:50051",
6
- # For defaults see https://github.com/grpc/grpc/blob/51f0d35509bcdaba572d422c4f856208162022de/src/ruby/lib/grpc/generic/rpc_server.rb#L186-L216
7
- rpc_pool_size: ::GRPC::RpcServer::DEFAULT_POOL_SIZE,
8
- rpc_max_waiting_requests: ::GRPC::RpcServer::DEFAULT_MAX_WAITING_REQUESTS,
9
- rpc_poll_period: ::GRPC::RpcServer::DEFAULT_POLL_PERIOD,
10
- rpc_pool_keep_alive: ::GRPC::Pool::DEFAULT_KEEP_ALIVE,
11
- # https://github.com/grpc/grpc/blob/f526602bff029b8db50a8d57134d72da33d8a752/include/grpc/impl/codegen/grpc_types.h#L141-L351
6
+ rpc_pool_size: 30,
7
+ rpc_max_waiting_requests: 20,
8
+ rpc_poll_period: 1,
9
+ rpc_pool_keep_alive: 0.25,
12
10
  rpc_server_args: {},
11
+ rpc_max_connection_age: 300,
13
12
  log_grpc: false
14
13
  )
15
14
 
@@ -33,7 +32,7 @@ module AnyCable
33
32
  max_waiting_requests: rpc_max_waiting_requests,
34
33
  poll_period: rpc_poll_period,
35
34
  pool_keep_alive: rpc_pool_keep_alive,
36
- server_args: normalized_grpc_server_args
35
+ server_args: enhance_grpc_server_args(normalized_grpc_server_args)
37
36
  }
38
37
  end
39
38
 
@@ -46,6 +45,14 @@ module AnyCable
46
45
  skey.start_with?("grpc.") ? skey : "grpc.#{skey}"
47
46
  end
48
47
  end
48
+
49
+ def enhance_grpc_server_args(opts)
50
+ return opts if opts.key?("grpc.max_connection_age_ms")
51
+ return opts unless rpc_max_connection_age.to_i > 0
52
+
53
+ opts["grpc.max_connection_age_ms"] = rpc_max_connection_age.to_i * 1000
54
+ opts
55
+ end
49
56
  end
50
57
  end
51
58
  end
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "anycable/grpc/handler"
4
+
5
+ module AnyCable
6
+ module GRPC
7
+ raise LoadError, "AnyCable::GRPC::Server has been already loaded!" if defined?(AnyCable::GRPC::Server)
8
+
9
+ using(Module.new do
10
+ refine ::GrpcKit::Server do
11
+ attr_reader :max_pool_size
12
+
13
+ def stopped?
14
+ @stopping
15
+ end
16
+ end
17
+ end)
18
+
19
+ # Wrapper over gRPC kit server.
20
+ #
21
+ # Basic example:
22
+ #
23
+ # # create new server listening on the loopback interface with 50051 port
24
+ # server = AnyCable::GrpcKit::Server.new(host: "127.0.0.1:50051")
25
+ #
26
+ # # run gRPC server in bakground
27
+ # server.start
28
+ #
29
+ # # stop server
30
+ # server.stop
31
+ class Server
32
+ attr_reader :grpc_server, :host, :hostname, :port, :sock
33
+
34
+ def initialize(host:, logger: nil, **options)
35
+ @logger = logger
36
+ @host = host
37
+
38
+ host_parts = host.match(/\A(?<hostname>.+):(?<port>\d{2,5})\z/)
39
+
40
+ @hostname = host_parts[:hostname]
41
+ @port = host_parts[:port].to_i
42
+
43
+ @grpc_server = build_server(**options)
44
+ end
45
+
46
+ # Start gRPC server in background and
47
+ # wait untill it ready to accept connections
48
+ def start
49
+ return if running?
50
+
51
+ raise "Cannot re-start stopped server" if stopped?
52
+
53
+ logger.info "RPC server (grpc_kit) is starting..."
54
+
55
+ @sock = TCPServer.new(hostname, port)
56
+
57
+ server = grpc_server
58
+
59
+ @start_thread = Thread.new do
60
+ loop do
61
+ conn = @sock.accept
62
+ server.run(conn)
63
+ rescue IOError
64
+ # ignore broken connections
65
+ end
66
+ end
67
+
68
+ wait_till_running
69
+
70
+ logger.info "RPC server is listening on #{host} (workers_num: #{grpc_server.max_pool_size})"
71
+ end
72
+
73
+ def wait_till_running
74
+ raise "Server is not running" unless running?
75
+
76
+ timeout = 5
77
+
78
+ loop do
79
+ sock = TCPSocket.new(hostname, port, connect_timeout: 1)
80
+ stub = AnyCable::GRPC::Stub.new(sock)
81
+ stub.connect(AnyCable::ConnectionRequest.new(env: {}))
82
+ sock.close
83
+ break
84
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, SocketError
85
+ timeout -= 1
86
+ raise "Server is not responding" if timeout.zero?
87
+ end
88
+ end
89
+
90
+ def wait_till_terminated
91
+ raise "Server is not running" unless running?
92
+
93
+ start_thread.join
94
+ end
95
+
96
+ # Stop gRPC server if it's running
97
+ def stop
98
+ return unless running?
99
+
100
+ return if stopped?
101
+
102
+ grpc_server.graceful_shutdown
103
+ sock.close
104
+
105
+ logger.info "RPC server stopped"
106
+ end
107
+
108
+ def running?
109
+ !!sock
110
+ end
111
+
112
+ def stopped?
113
+ grpc_server.stopped?
114
+ end
115
+
116
+ private
117
+
118
+ attr_reader :start_thread
119
+
120
+ def logger
121
+ @logger ||= AnyCable.logger
122
+ end
123
+
124
+ def build_server(**options)
125
+ pool_size = options[:pool_size]
126
+
127
+ ::GrpcKit::Server.new(min_pool_size: pool_size, max_pool_size: pool_size).tap do |server|
128
+ server.handle(AnyCable::GRPC::Handler)
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "grpc_kit"
4
+
5
+ module AnyCable
6
+ module GRPC
7
+ end
8
+ end
9
+
10
+ require "anycable/grpc/config"
11
+ require "anycable/grpc_kit/server"
12
+
13
+ AnyCable.server_builder = ->(config) {
14
+ AnyCable.logger.info "gRPC Kit version: #{::GrpcKit::VERSION}"
15
+
16
+ ::GrpcKit.loglevel = :fatal
17
+ ::GrpcKit.logger = AnyCable.logger if config.log_grpc?
18
+
19
+ params = config.to_grpc_params
20
+
21
+ AnyCable::GRPC::Server.new(**params, host: config.rpc_host)
22
+ }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AnyCable
4
- VERSION = "1.2.5"
4
+ VERSION = "1.3.0"
5
5
  end
data/lib/anycable.rb CHANGED
@@ -109,11 +109,23 @@ module AnyCable
109
109
  end
110
110
  end
111
111
 
112
- # gRPC is the default for now, so, let's try to load it.
113
- begin
114
- require "anycable/grpc"
115
- rescue LoadError => e
116
- # Re-raise an exception if we failed to load grpc .so files
117
- # (e.g., on Alpine Linux)
118
- raise if /(error loading shared library|incompatible architecture)/i.match?(e.message)
112
+ # Try loading a gRPC implementation
113
+ impl = ENV.fetch("ANYCABLE_GRPC_IMPL", "grpc")
114
+
115
+ case impl
116
+ when "grpc"
117
+ begin
118
+ require "grpc/version"
119
+ require "anycable/grpc"
120
+ rescue LoadError => e
121
+ # Re-raise an exception if we failed to load grpc .so files
122
+ # (e.g., on Alpine Linux)
123
+ raise if /(error loading shared library|incompatible architecture)/i.match?(e.message)
124
+ end
125
+ when "grpc_kit"
126
+ begin
127
+ require "grpc_kit/version"
128
+ require "anycable/grpc_kit"
129
+ rescue LoadError
130
+ end
119
131
  end
@@ -1,5 +1,7 @@
1
1
  module AnyCable
2
2
  interface _Config
3
+ def presets: () -> Array[String]
4
+ def presets=: (Array[String]) -> void
3
5
  def broadcast_adapter: () -> Symbol
4
6
  def broadcast_adapter=: (Symbol) -> void
5
7
  def redis_url: () -> String
@@ -9,14 +11,19 @@ module AnyCable
9
11
  def redis_channel: () -> String
10
12
  def redis_channel=: (String) -> void
11
13
  def redis_tls_verify: () -> bool
12
- def redis_tls_verify?: () -> bool
13
14
  def redis_tls_verify=: (bool) -> void
15
+ def redis_tls_verify?: () -> bool
16
+ def redis_tls_client_cert_path: () -> String?
17
+ def redis_tls_client_cert_path=: (String) -> void
18
+ def redis_tls_client_key_path: () -> String?
19
+ def redis_tls_client_key_path=: (String) -> void
14
20
  def nats_servers: () -> Array[String]
15
21
  def nats_servers=: (Array[String]) -> void
16
22
  def nats_channel: () -> String
17
23
  def nats_channel=: (String) -> void
18
24
  def nats_dont_randomize_servers: () -> bool
19
25
  def nats_dont_randomize_servers=: (bool) -> void
26
+ def nats_dont_randomize_servers?: () -> bool
20
27
  def nats_options: () -> Hash[untyped, untyped]
21
28
  def nats_options=: (Hash[untyped, untyped]) -> void
22
29
  def http_broadcast_url: () -> String
@@ -29,12 +36,17 @@ module AnyCable
29
36
  def log_level=: (String) -> void
30
37
  def debug: () -> bool
31
38
  def debug=: (bool) -> void
39
+ def debug?: () -> bool
32
40
  def http_health_port: () -> Integer?
33
41
  def http_health_port=: (Integer) -> void
34
42
  def http_health_path: () -> String
35
43
  def http_health_path=: (String) -> void
36
44
  def version_check_enabled: () -> bool
37
45
  def version_check_enabled=: (bool) -> void
46
+ def version_check_enabled?: () -> bool
47
+ def sid_header_enabled: () -> bool
48
+ def sid_header_enabled=: (bool) -> void
49
+ def sid_header_enabled?: () -> bool
38
50
  end
39
51
 
40
52
  class Config < Anyway::Config
@@ -46,6 +58,7 @@ module AnyCable
46
58
  alias debug? debug
47
59
  alias version_check_enabled? version_check_enabled
48
60
 
61
+ def load: (*untyped) -> void
49
62
  def http_health_port_provided?: () -> bool
50
63
  def to_redis_params: () -> { url: String, sentinels: Array[untyped]?, ssl_params: Hash[Symbol, untyped]? }
51
64
  def to_http_health_params: () -> { port: Integer?, path: String }
@@ -54,5 +67,10 @@ module AnyCable
54
67
  private
55
68
 
56
69
  def parse_sentinel: ((String | Hash[untyped, untyped]) sentinel) -> Hash[Symbol, untyped]
70
+ def load_presets: () -> void
71
+ def detect_presets: () -> Array[String]
72
+ def write_preset: (Symbol, untyped, preset: String) -> void
73
+ def write_config_attr: (Symbol, untyped) -> void
74
+ def __trace__: () -> untyped
57
75
  end
58
76
  end
@@ -7,30 +7,38 @@ module AnyCable
7
7
  def rpc_pool_size=: (Integer) -> void
8
8
  def rpc_max_waiting_requests: () -> Integer
9
9
  def rpc_max_waiting_requests=: (Integer) -> void
10
- def rpc_poll_period: () -> Integer
11
- def rpc_poll_period=: (Integer) -> void
12
- def rpc_pool_keep_alive: () -> Integer
13
- def rpc_pool_keep_alive=: (Integer) -> void
10
+ def rpc_poll_period: () -> Numeric
11
+ def rpc_poll_period=: (Numeric) -> void
12
+ def rpc_pool_keep_alive: () -> Numeric
13
+ def rpc_pool_keep_alive=: (Numeric) -> void
14
+ def rpc_max_connection_age: () -> Integer
15
+ def rpc_max_connection_age=: (Integer) -> void
14
16
  def rpc_server_args: () -> Hash[Symbol | String, untyped]?
15
17
  def rpc_server_args=: (Hash[Symbol | String, untyped]) -> void
16
18
  def log_grpc: () -> bool
17
19
  def log_grpc=: (bool) -> void
20
+ def log_grpc?: () -> bool
18
21
  end
19
22
 
20
- module Config : AnyCable::Config
23
+ module Config : AnyCable::_Config
21
24
  include _Config
22
25
 
23
- alias log_grpc? log_grpc
24
-
25
26
  def to_grpc_params: () -> {
26
27
  pool_size: Integer,
27
28
  max_waiting_requests: Integer,
28
- poll_period: Integer,
29
- pool_keep_alive: Integer,
29
+ poll_period: Numeric,
30
+ pool_keep_alive: Numeric,
30
31
  server_args: Hash[String, untyped]
31
32
  }
32
33
 
33
34
  def normalized_grpc_server_args: () -> Hash[String, untyped]
35
+ def enhance_grpc_server_args: (Hash[String, untyped]) -> Hash[String, untyped]
34
36
  end
35
37
  end
36
38
  end
39
+
40
+ module AnyCable
41
+ class Config
42
+ include GRPC::Config
43
+ end
44
+ end
@@ -6,7 +6,7 @@ module AnyCable
6
6
  attr_reader grpc_server: untyped
7
7
  attr_reader host: String
8
8
 
9
- def initialize: (host: String, ?logger: Logger, **untyped options) -> void
9
+ def initialize: (host: String, ?logger: Logger?, **untyped options) -> void
10
10
 
11
11
  private
12
12
 
@@ -12,7 +12,7 @@ module AnyCable
12
12
  attr_reader path: String
13
13
  attr_reader http_server: untyped
14
14
 
15
- def initialize: (_Runnable server, port: Integer port, ?logger: Logger logger, ?path: String path) -> void
15
+ def initialize: (_Runnable server, port: Integer port, ?logger: Logger? logger, ?path: String path) -> void
16
16
  def start: () -> void
17
17
  def stop: () -> void
18
18
  def running?: () -> bool
@@ -1,5 +1,5 @@
1
1
  module AnyCable
2
2
  class Middleware
3
- def call: (Symbol, rpcRequest, rpcMetadata) { (Symbol, rpcRequest, rpcMetadata) -> rpcResponse } -> rpcResponse
3
+ def call: (Symbol, rpcRequest, rpcMetadata) { () -> rpcResponse } -> rpcResponse
4
4
  end
5
5
  end
data/sig/anycable/rpc.rbs CHANGED
@@ -12,6 +12,12 @@ module AnyCable
12
12
  type protoMap = _ProtobufMap
13
13
  type rpcMetadata = Hash[String, String]
14
14
 
15
+ module Status
16
+ SUCCESS: 0
17
+ FAILURE: 1
18
+ ERROR: 2
19
+ end
20
+
15
21
  interface _WithEnvState
16
22
  def cstate: () -> protoMap?
17
23
  def cstate=: (protoMap) -> void
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: anycable-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.5
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - palkan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-01 00:00:00.000000000 Z
11
+ date: 2023-03-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: anyway_config
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 2.1.0
19
+ version: '2.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 2.1.0
26
+ version: '2.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: google-protobuf
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -122,6 +122,34 @@ dependencies:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '3.5'
125
+ - !ruby/object:Gem::Dependency
126
+ name: simplecov
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: simplecov-lcov
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
125
153
  - !ruby/object:Gem::Dependency
126
154
  name: webmock
127
155
  requirement: !ruby/object:Gem::Requirement
@@ -181,6 +209,8 @@ files:
181
209
  - lib/anycable/grpc/handler.rb
182
210
  - lib/anycable/grpc/rpc_services_pb.rb
183
211
  - lib/anycable/grpc/server.rb
212
+ - lib/anycable/grpc_kit.rb
213
+ - lib/anycable/grpc_kit/server.rb
184
214
  - lib/anycable/health_server.rb
185
215
  - lib/anycable/middleware.rb
186
216
  - lib/anycable/middleware_chain.rb
@@ -241,14 +271,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
241
271
  requirements:
242
272
  - - ">="
243
273
  - !ruby/object:Gem::Version
244
- version: 2.6.0
274
+ version: 2.7.0
245
275
  required_rubygems_version: !ruby/object:Gem::Requirement
246
276
  requirements:
247
277
  - - ">="
248
278
  - !ruby/object:Gem::Version
249
279
  version: '0'
250
280
  requirements: []
251
- rubygems_version: 3.3.11
281
+ rubygems_version: 3.4.6
252
282
  signing_key:
253
283
  specification_version: 4
254
284
  summary: AnyCable core RPC implementation