anycable-core 1.2.0 → 1.2.1

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: b4c85f8eab809e414507ed9e35da7381b9ca2626ad4c9e2e4f84a5ee8dda2d09
4
- data.tar.gz: 37edd04f4c524384c989a774f94e7a8ede624f7fe95e3a6f1a864f2c11f03b4e
3
+ metadata.gz: 5f387a5b5a0a7535f698339c719f4f7f8debd3c799f5e69b7b54b46b599d3830
4
+ data.tar.gz: 558f452d571cd33557836861083539fa130c266d5ded16764f0137a9494c39d2
5
5
  SHA512:
6
- metadata.gz: 15602cd4712a4a451e41c03035b176d0fc276593852ab93f386e588d297f7a3e7be8284e8feb952fb19b8a0918973edb48c6a9ce2bd0fb8a63a0ceb068c12730
7
- data.tar.gz: a8453ffddde915bd88e2c5fd8cad6178194c8ca7ad3193f617157c6a92b5504022d4a11572e7bb61cc9157897857ab00b7dbab609961ee9ad7d9b55321f66ea9
6
+ metadata.gz: 819b9da9e51dae8e6feca6be71550c72e3aaee4358e8245c95235a030f9ee130d3b49d48590eb3d4abc8275a7918c71130b48fd63e3b4b9a5fd46d34520942c7
7
+ data.tar.gz: c3409d81a2b9c66593384de64d0cc66ac1c31d915d58a836af1c222438d152f18ca86830a86c7867b784ba2159aa80787a5abd5ea3b50d8edd99b835d572bbe8
data/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.2.1 (2022-02-21)
6
+
7
+ - Fix RBS signature. ([@palkan][])
8
+
9
+ - Add empty (`''`) service to gRPC health check as "NOT_SERVING". ([@palkan][])
10
+
5
11
  ## 1.2.0 (2021-12-21) 🎄
6
12
 
7
13
  - Drop Ruby 2.6 support.
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2017-2021 Vladimir Dementyev
1
+ Copyright 2017-2022 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,6 +1,5 @@
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
- [![Gitter](https://img.shields.io/badge/gitter-join%20chat%20%E2%86%92-brightgreen.svg)](https://gitter.im/anycable/Lobby)
4
3
  [![Documentation](https://img.shields.io/badge/docs-link-brightgreen.svg)](https://docs.anycable.io/v1)
5
4
 
6
5
  # AnyCable
@@ -30,7 +30,7 @@ module AnyCable
30
30
  **options
31
31
  )
32
32
  options = AnyCable.config.to_redis_params.merge(options)
33
- @redis_conn = ::Redis.new(options)
33
+ @redis_conn = ::Redis.new(**options)
34
34
  @channel = channel
35
35
  end
36
36
 
data/lib/anycable/cli.rb CHANGED
@@ -119,7 +119,7 @@ module AnyCable
119
119
  def wait_till_terminated
120
120
  self_read = setup_signals
121
121
 
122
- while readable_io = IO.select([self_read]) # rubocop:disable Lint/AssignmentInCondition
122
+ while readable_io = IO.select([self_read]) # rubocop:disable Lint/AssignmentInCondition,Lint/IncompatibleIoSelectWithFiberScheduler
123
123
  signal = readable_io.first[0].gets.strip
124
124
  raise Interrupt, "SIG#{signal} received"
125
125
  end
@@ -74,7 +74,7 @@ module AnyCable
74
74
 
75
75
  HTTP HEALTH CHECKER
76
76
  --http-health-port=port Port to run HTTP health server on, default: <none> (disabled)
77
- --http-health-path=path Endpoint to server health cheks, default: "/health"
77
+ --http-health-path=path Endpoint to serve health checks, default: "/health"
78
78
 
79
79
  REDIS PUB/SUB
80
80
  --redis-url=url Redis URL for pub/sub, default: REDIS_URL or "redis://localhost:6379/5"
@@ -96,6 +96,10 @@ module AnyCable
96
96
  "anycable.RPC",
97
97
  Grpc::Health::V1::HealthCheckResponse::ServingStatus::SERVING
98
98
  )
99
+ health_checker.add_status(
100
+ "",
101
+ Grpc::Health::V1::HealthCheckResponse::ServingStatus::NOT_SERVING
102
+ )
99
103
  health_checker
100
104
  end
101
105
  end
@@ -65,7 +65,15 @@ module AnyCable
65
65
  AccessLog: []
66
66
  ).tap do |http_server|
67
67
  http_server.mount_proc path do |_, res|
68
- res.status, res.body = server.running? ? SUCCESS_RESPONSE : FAILURE_RESPONSE
68
+ # Replace with mass assignment as soon as Steep added support
69
+ # https://github.com/soutaro/steep/issues/424
70
+ if server.running?
71
+ res.status = SUCCESS_RESPONSE.first
72
+ res.body = SUCCESS_RESPONSE.last
73
+ else
74
+ res.status = FAILURE_RESPONSE.first
75
+ res.body = FAILURE_RESPONSE.last
76
+ end
69
77
  end
70
78
  end
71
79
  end
@@ -116,22 +116,23 @@ module AnyCable
116
116
  # Build Rack env from request
117
117
  def build_rack_env
118
118
  uri = URI.parse(request_env.url)
119
+ headers = request_env.headers.to_h
119
120
 
120
121
  env = base_rack_env
121
122
  env.merge!({
122
123
  "PATH_INFO" => uri.path,
123
124
  "QUERY_STRING" => uri.query,
124
125
  "SERVER_NAME" => uri.host,
125
- "SERVER_PORT" => uri.port,
126
+ "SERVER_PORT" => uri.port&.to_s,
126
127
  "HTTP_HOST" => uri.host,
127
- "REMOTE_ADDR" => request_env.headers.delete("REMOTE_ADDR"),
128
+ "REMOTE_ADDR" => headers.delete("REMOTE_ADDR"),
128
129
  "rack.url_scheme" => uri.scheme&.sub(/^ws/, "http"),
129
130
  # AnyCable specific fields
130
131
  "anycable.raw_cstate" => request_env.cstate&.to_h,
131
132
  "anycable.raw_istate" => request_env.istate&.to_h
132
133
  }.delete_if { |_k, v| v.nil? })
133
134
 
134
- env.merge!(build_headers(request_env.headers))
135
+ env.merge!(build_headers(headers))
135
136
  end
136
137
 
137
138
  def base_rack_env
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AnyCable
4
- VERSION = "1.2.0"
4
+ VERSION = "1.2.1"
5
5
  end
data/lib/anycable.rb CHANGED
@@ -114,5 +114,5 @@ begin
114
114
  rescue LoadError => e
115
115
  # Re-raise an exception if we failed to load grpc .so files
116
116
  # (e.g., on Alpine Linux)
117
- raise if /Error loading shared library/.match?(e.message)
117
+ raise if /(error loading shared library|incompatible architecture)/i.match?(e.message)
118
118
  end
@@ -0,0 +1,18 @@
1
+ module AnyCable
2
+ interface _BroadcastAdapter
3
+ def raw_broadcast: (String _data) -> void
4
+ def broadcast: (String stream, String payload) -> void
5
+ def broadcast_command: (String command, **untyped payload) -> void
6
+ def announce!: () -> void
7
+ end
8
+
9
+ module BroadcastAdapters
10
+ class Base
11
+ include _BroadcastAdapter
12
+
13
+ private
14
+
15
+ def logger: () -> Logger
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,31 @@
1
+ module AnyCable
2
+ module BroadcastAdapters
3
+ class Http < Base
4
+ RECOVERABLE_EXCEPTIONS: Array[singleton(Class)]
5
+ OPEN_TIMEOUT: Integer
6
+ READ_TIMEOUT: Integer
7
+ MAX_ATTEMPTS: Integer
8
+ DELAY: Integer
9
+
10
+ attr_reader url: String
11
+ attr_reader headers: Hash[String, String]
12
+ attr_reader authorized: bool
13
+
14
+ alias authorized? authorized
15
+
16
+ def initialize: (?url: String url, ?secret: String secret) -> void
17
+ def shutdown: () -> void
18
+
19
+ private
20
+
21
+ attr_reader uri: URI::Generic
22
+ attr_reader queue: Thread::Queue
23
+ attr_reader thread: Thread?
24
+
25
+ def ensure_thread_is_alive: () -> void
26
+ def perform_request: (String payload) -> untyped
27
+ def handle_response: (untyped response) -> void
28
+ def build_http: () { (untyped) -> untyped } -> untyped
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,10 @@
1
+ module AnyCable
2
+ module BroadcastAdapters
3
+ class Redis < Base
4
+ attr_reader redis_conn: untyped
5
+ attr_reader channel: String
6
+
7
+ def initialize: (?channel: String channel, **untyped options) -> void
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,36 @@
1
+ module AnyCable
2
+ module GRPC
3
+ interface _Config
4
+ def rpc_host: () -> String
5
+ def rpc_host=: (String) -> void
6
+ def rpc_pool_size: () -> Integer
7
+ def rpc_pool_size=: (Integer) -> void
8
+ def rpc_max_waiting_requests: () -> Integer
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
14
+ def rpc_server_args: () -> Hash[Symbol | String, untyped]?
15
+ def rpc_server_args=: (Hash[Symbol | String, untyped]) -> void
16
+ def log_grpc: () -> bool
17
+ def log_grpc=: (bool) -> void
18
+ end
19
+
20
+ module Config : AnyCable::Config
21
+ include _Config
22
+
23
+ alias log_grpc? log_grpc
24
+
25
+ def to_grpc_params: () -> {
26
+ pool_size: Integer,
27
+ max_waiting_requests: Integer,
28
+ poll_period: Integer,
29
+ pool_keep_alive: Integer,
30
+ server_args: Hash[String, untyped]
31
+ }
32
+
33
+ def normalized_grpc_server_args: () -> Hash[String, untyped]
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,11 @@
1
+ module AnyCable
2
+ module GRPC
3
+ # RPC service handler
4
+ class Handler < AnyCable::GRPC::Service
5
+ # Handle connection request from WebSocket server
6
+ def connect: (untyped request, untyped _unused_call) -> untyped
7
+ def disconnect: (untyped request, untyped _unused_call) -> untyped
8
+ def command: (untyped request, untyped _unused_call) -> untyped
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ module AnyCable
2
+ module GRPC
3
+ class Service
4
+ end
5
+
6
+ Stub: untyped
7
+ end
8
+ end
@@ -0,0 +1,20 @@
1
+ module AnyCable
2
+ module GRPC
3
+ class Server
4
+ include _Server
5
+
6
+ attr_reader grpc_server: untyped
7
+ attr_reader host: String
8
+
9
+ def initialize: (host: String, ?logger: Logger, **untyped options) -> void
10
+
11
+ private
12
+
13
+ attr_reader start_thread: Thread
14
+
15
+ def logger: () -> Logger
16
+ def build_server: (**untyped options) -> untyped
17
+ def build_health_checker: () -> untyped
18
+ end
19
+ end
20
+ end
@@ -1,14 +1,18 @@
1
1
  module AnyCable
2
2
  class HealthServer
3
+ interface _Runnable
4
+ def running?: () -> bool
5
+ end
6
+
3
7
  SUCCESS_RESPONSE: Array[Integer | String]
4
8
  FAILURE_RESPONSE: Array[Integer | String]
5
9
 
6
- attr_reader server: _Server
10
+ attr_reader server: _Runnable
7
11
  attr_reader port: Integer
8
12
  attr_reader path: String
9
13
  attr_reader http_server: untyped
10
14
 
11
- def initialize: (_Server 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
12
16
  def start: () -> void
13
17
  def stop: () -> void
14
18
  def running?: () -> bool
@@ -0,0 +1,10 @@
1
+ module AnyCable
2
+ module Middlewares
3
+ class CheckVersion < AnyCable::Middleware
4
+ attr_reader version: String
5
+
6
+ def initialize: (String version) -> void
7
+ def check_version: (rpcMetadata) { () -> untyped } -> untyped
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module AnyCable
2
+ module Middlewares
3
+ class Exceptions < AnyCable::Middleware
4
+ private
5
+
6
+ def notify_exception: (StandardError exp, Symbol method_name, rpcRequest request) -> void
7
+ def response_class: (Symbol method_name) -> untyped
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,24 @@
1
+ module AnyCable
2
+ module RPC
3
+ interface _Handler
4
+ def build_socket: (env: Env) -> Socket
5
+ def build_env_response: (Socket socket) -> EnvResponse
6
+ def logger: () -> Logger
7
+ def factory: () -> _ConnectionFactory
8
+ end
9
+
10
+ class Handler
11
+ include _Handler
12
+ include Handlers::Connect
13
+ include Handlers::Disconnect
14
+ include Handlers::Command
15
+
16
+ def initialize: (?middleware: MiddlewareChain) -> void
17
+ def handle: (Symbol cmd, rpcRequest data, ?rpcMetadata meta) -> rpcResponse
18
+
19
+ private
20
+
21
+ attr_reader middleware: MiddlewareChain
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,9 @@
1
+ module AnyCable
2
+ module RPC
3
+ module Handlers
4
+ module Command : _Handler
5
+ def command: (CommandMessage message) -> CommandResponse
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module AnyCable
2
+ module RPC
3
+ module Handlers
4
+ module Connect : _Handler
5
+ def connect: (ConnectionRequest request) -> ConnectionResponse
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module AnyCable
2
+ module RPC
3
+ module Handlers
4
+ module Disconnect : _Handler
5
+ def disconnect: (DisconnectRequest request) -> DisconnectResponse
6
+ end
7
+ end
8
+ end
9
+ end
data/sig/anycable/rpc.rbs CHANGED
@@ -2,8 +2,14 @@ module AnyCable
2
2
  PROTO_VERSION: ::String
3
3
  SESSION_KEY: ::String
4
4
 
5
+ interface _ProtobufMap
6
+ def []: (String key) -> String
7
+ def []=: (String key, String val) -> String
8
+ def to_h: () -> Hash[String, String]
9
+ end
10
+
5
11
  type rpcStatus = 0 | 1 | 2
6
- type protoMap = Hash[String, String]
12
+ type protoMap = _ProtobufMap
7
13
  type rpcMetadata = Hash[String, String]
8
14
 
9
15
  interface _WithEnvState
@@ -38,7 +44,7 @@ module AnyCable
38
44
  end
39
45
 
40
46
  module WithConnectionState : _WithEnv, _ProtoMessage
41
- def initialize: (?session: untyped? session, **untyped other) -> untyped
47
+ %a{rbs:test:skip} def initialize: (?session: untyped? session, **untyped other) -> untyped
42
48
 
43
49
  def session=: (untyped val) -> untyped
44
50
  def session: () -> untyped
@@ -60,8 +66,8 @@ module AnyCable
60
66
  class ConnectionRequest
61
67
  include _WithEnv
62
68
 
63
- def initialize: (?env: Env) -> void
64
- def to_h: () -> Hash[String, untyped]
69
+ %a{rbs:test:skip} def initialize: (?env: Env) -> void
70
+ def to_h: () -> Hash[Symbol, untyped]
65
71
  end
66
72
 
67
73
  class ConnectionResponse
@@ -73,7 +79,7 @@ module AnyCable
73
79
  attr_accessor error_msg: String?
74
80
  attr_accessor env: EnvResponse
75
81
 
76
- def initialize: (
82
+ %a{rbs:test:skip} def initialize: (
77
83
  status: rpcStatus,
78
84
  ?identifiers: String,
79
85
  ?transmissions: Array[String],
@@ -81,7 +87,7 @@ module AnyCable
81
87
  ?env: EnvResponse
82
88
  ) -> void
83
89
 
84
- def to_h: () -> Hash[String, untyped]
90
+ def to_h: () -> Hash[Symbol, untyped]
85
91
  end
86
92
 
87
93
  class CommandMessage
@@ -92,14 +98,14 @@ module AnyCable
92
98
  attr_accessor connection_identifiers: String
93
99
  attr_accessor data: String
94
100
 
95
- def initialize: (
101
+ %a{rbs:test:skip} def initialize: (
96
102
  command: String,
97
103
  identifier: String,
98
104
  ?connection_identifiers: String,
99
105
  ?env: Env
100
106
  ) -> void
101
107
 
102
- def to_h: () -> Hash[String, untyped]
108
+ def to_h: () -> Hash[Symbol, untyped]
103
109
  end
104
110
 
105
111
  class CommandResponse
@@ -114,7 +120,7 @@ module AnyCable
114
120
  attr_accessor env: EnvResponse
115
121
  attr_accessor stopped_streams: Array[String]
116
122
 
117
- def initialize: (
123
+ %a{rbs:test:skip} def initialize: (
118
124
  status: rpcStatus,
119
125
  ?disconnect: bool,
120
126
  ?stop_streams: bool,
@@ -125,7 +131,7 @@ module AnyCable
125
131
  ?env: EnvResponse
126
132
  ) -> void
127
133
 
128
- def to_h: () -> Hash[String, untyped]
134
+ def to_h: () -> Hash[Symbol, untyped]
129
135
  end
130
136
 
131
137
  class DisconnectRequest
@@ -134,8 +140,8 @@ module AnyCable
134
140
  attr_accessor identifiers: String
135
141
  attr_accessor subscriptions: Array[String]
136
142
 
137
- def initialize: (identifiers: String, ?subscriptions: Array[String], ?env: Env) -> void
138
- def to_h: () -> Hash[String, untyped]
143
+ %a{rbs:test:skip} def initialize: (identifiers: String, ?subscriptions: Array[String], ?env: Env) -> void
144
+ def to_h: () -> Hash[Symbol, untyped]
139
145
  end
140
146
 
141
147
  class DisconnectResponse
@@ -144,8 +150,8 @@ module AnyCable
144
150
  attr_accessor status: rpcStatus
145
151
  attr_accessor error_msg: String?
146
152
 
147
- def initialize: (status: rpcStatus, ?error_msg: String) -> void
148
- def to_h: () -> Hash[String, untyped]
153
+ %a{rbs:test:skip} def initialize: (status: rpcStatus, ?error_msg: String) -> void
154
+ def to_h: () -> Hash[Symbol, untyped]
149
155
  end
150
156
 
151
157
  type rpcRequest = ConnectionRequest | DisconnectRequest | CommandMessage
@@ -2,12 +2,12 @@ module AnyCable
2
2
  class Socket
3
3
  class State
4
4
  attr_reader dirty_keys: Array[String]?
5
- attr_reader source: protoMap
5
+ attr_reader source: Hash[String, String]
6
6
 
7
- def initialize: (protoMap) -> void
7
+ def initialize: (Hash[String, String]) -> void
8
8
  def read: (String key) -> untyped
9
9
  def write: (String key, String val) -> void
10
- def changed_fields: () -> protoMap?
10
+ def changed_fields: () -> Hash[String, String]?
11
11
 
12
12
  alias [] read
13
13
  alias []= write
data/sig/anycable.rbs CHANGED
@@ -18,7 +18,11 @@ module AnyCable
18
18
 
19
19
  type serverBuilder = ^(Config) -> _Server
20
20
 
21
- attr_accessor self.connection_factory: ^(Socket, ?identifiers: String, ?subscriptions: Array[String]) -> _Connection
21
+ interface _ConnectionFactory
22
+ def call: (Socket, ?identifiers: String, ?subscriptions: Array[String]) -> _Connection
23
+ end
24
+
25
+ attr_accessor self.connection_factory: _ConnectionFactory
22
26
  attr_accessor self.server_builder: serverBuilder
23
27
  attr_writer self.logger: Logger
24
28
  attr_writer self.rpc_handler: RPC::Handler
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.0
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - palkan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-21 00:00:00.000000000 Z
11
+ date: 2022-02-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: anyway_config
@@ -136,20 +136,6 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
- - !ruby/object:Gem::Dependency
140
- name: steep
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'
153
139
  description: AnyCable core RPC implementation not depenending on a particular server
154
140
  type (e.g., gRPC or whatever)
155
141
  email:
@@ -197,13 +183,26 @@ files:
197
183
  - lib/anycable/version.rb
198
184
  - sig/anycable.rbs
199
185
  - sig/anycable/broadcast_adapters.rbs
186
+ - sig/anycable/broadcast_adapters/base.rbs
187
+ - sig/anycable/broadcast_adapters/http.rbs
188
+ - sig/anycable/broadcast_adapters/redis.rbs
200
189
  - sig/anycable/cli.rbs
201
190
  - sig/anycable/config.rbs
202
191
  - sig/anycable/exceptions_handling.rbs
192
+ - sig/anycable/grpc/config.rbs
193
+ - sig/anycable/grpc/handler.rbs
194
+ - sig/anycable/grpc/rpc_services_pb.rbs
195
+ - sig/anycable/grpc/server.rbs
203
196
  - sig/anycable/health_server.rbs
204
197
  - sig/anycable/middleware.rbs
205
198
  - sig/anycable/middleware_chain.rbs
199
+ - sig/anycable/middlewares/check_version.rbs
200
+ - sig/anycable/middlewares/exceptions.rbs
206
201
  - sig/anycable/rpc.rbs
202
+ - sig/anycable/rpc/handler.rbs
203
+ - sig/anycable/rpc/handlers/command.rbs
204
+ - sig/anycable/rpc/handlers/connect.rbs
205
+ - sig/anycable/rpc/handlers/disconnect.rbs
207
206
  - sig/anycable/socket.rbs
208
207
  - sig/anycable/version.rbs
209
208
  homepage: http://github.com/anycable/anycable