async-cable 0.1.0 → 0.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: 8d7aec9e4d2af6f7e33c0684d7e5f1d7ec6484cd055f2be48bd08b4f635935a5
4
- data.tar.gz: 4bac0fc445833442bab84556ca34aed98872e9f1d250b411a8abfef777c85555
3
+ metadata.gz: b9aa3fe6a825d58f713ffd71b32b26bd034de7f3175ee6b9505e4f53433f6999
4
+ data.tar.gz: 5bea7df4792f6f0bf2ed0847437ac13f23972de50b443854f597b4f9b8b6defa
5
5
  SHA512:
6
- metadata.gz: 3af7edbe1360eff3316b2fc88076476006ad39f607a20fdf112ddb40130dad0b9cd26316cc7c14e6c7af9cbe6a5320daab159ff71e219799ba9445592d523a2f
7
- data.tar.gz: 8c021590476f294e34448d59d629fd9499f082ba5a8ed68d72677f52c799fcbd2a10cc7872c10e6ccc317e093ec708c992c70b8e055478ce66b1576b814cb7df
6
+ metadata.gz: 2291b430d4dbfd1072d8dadb1643857e71e84ef749dd08f6bb97168cdb842af6edf6da703d41acc370d9899e0130fffd068ac568a0d5bf269306746e3aeefe11
7
+ data.tar.gz: aa8346b8289d1dbe14e606631506ee5a2801cef846a67b13cb0e092806f0da1c6cdf980358b43163c3b2a614fea71bd5f8363383051f741ff39a03794a0e5ff7
checksums.yaml.gz.sig CHANGED
Binary file
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Released under the MIT License.
3
4
  # Copyright, 2024, by Samuel Williams.
4
5
 
@@ -10,8 +11,9 @@ require_relative "socket"
10
11
  module Async
11
12
  module Cable
12
13
  class Middleware
13
- def initialize(app, server: ActionCable.server)
14
+ def initialize(app, path: "/cable", server: ActionCable.server)
14
15
  @app = app
16
+ @path = path
15
17
  @server = server
16
18
  @coder = ActiveSupport::JSON
17
19
  @protocols = ::ActionCable::INTERNAL[:protocols]
@@ -19,8 +21,12 @@ module Async
19
21
 
20
22
  attr :server
21
23
 
24
+ def valid_path?(env)
25
+ env["PATH_INFO"] == @path
26
+ end
27
+
22
28
  def call(env)
23
- if Async::WebSocket::Adapters::Rack.websocket?(env) and allow_request_origin?(env)
29
+ if valid_path?(env) and Async::WebSocket::Adapters::Rack.websocket?(env) and allow_request_origin?(env)
24
30
  Async::WebSocket::Adapters::Rack.open(env, protocols: @protocols) do |websocket|
25
31
  handle_incoming_websocket(env, websocket)
26
32
  end
@@ -42,13 +48,13 @@ module Async
42
48
  socket_task = socket.run
43
49
 
44
50
  while message = websocket.read
45
- Console.debug(self, "Received cable data:", message.buffer)
51
+ # Console.debug(self, "Received cable data:", message.buffer)
46
52
  connection.handle_incoming(@coder.decode(message.buffer))
47
53
  end
48
54
  rescue Protocol::WebSocket::ClosedError, EOFError
49
55
  # This is a normal disconnection.
50
56
  rescue => error
51
- Console.warn(self, error)
57
+ Console.warn(self, "Abnormal client failure!", error)
52
58
  ensure
53
59
  if connection
54
60
  @server.remove_connection(connection)
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Released under the MIT License.
3
4
  # Copyright, 2024, by Samuel Williams.
4
5
 
@@ -33,12 +34,16 @@ module Async::Cable
33
34
  def run(parent: Async::Task.current)
34
35
  parent.async do
35
36
  while buffer = @output.pop
37
+ # Console.debug(self, "Sending cable data:", buffer, flush: @output.empty?)
36
38
  @websocket.send_text(buffer)
37
39
  @websocket.flush if @output.empty?
38
40
  end
39
41
  rescue => error
42
+ Console.error(self, "Error while sending cable data:", error)
40
43
  ensure
41
- @websocket.close_write(error)
44
+ unless @websocket.closed?
45
+ @websocket.close_write(error)
46
+ end
42
47
  end
43
48
  end
44
49
 
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Released under the MIT License.
3
4
  # Copyright, 2023-2024, by Samuel Williams.
4
5
 
5
6
  module Async
6
7
  module Cable
7
- VERSION = "0.1.0"
8
+ VERSION = "0.3.0"
8
9
  end
9
10
  end
data/readme.md CHANGED
@@ -14,6 +14,14 @@ Please see the [project documentation](https://socketry.github.io/async-cable/)
14
14
 
15
15
  Please see the [project releases](https://socketry.github.io/async-cable/releases/index) for all releases.
16
16
 
17
+ ### v0.3.0
18
+
19
+ - Filter requests based on path - don't eat all inbound WebSocket connections.
20
+
21
+ ### v0.2.0
22
+
23
+ - Don't close the WebSocket if it is already closed.
24
+
17
25
  ### v0.1.0
18
26
 
19
27
  - Initial implementation.
data/releases.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Releases
2
2
 
3
+ ## v0.3.0
4
+
5
+ - Filter requests based on path - don't eat all inbound WebSocket connections.
6
+
7
+ ## v0.2.0
8
+
9
+ - Don't close the WebSocket if it is already closed.
10
+
3
11
  ## v0.1.0
4
12
 
5
13
  - Initial implementation.
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,11 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-cable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain:
11
10
  - |
@@ -37,7 +36,7 @@ cert_chain:
37
36
  Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
38
37
  voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
39
38
  -----END CERTIFICATE-----
40
- date: 2024-11-19 00:00:00.000000000 Z
39
+ date: 1980-01-02 00:00:00.000000000 Z
41
40
  dependencies:
42
41
  - !ruby/object:Gem::Dependency
43
42
  name: actioncable-next
@@ -81,13 +80,10 @@ dependencies:
81
80
  - - ">="
82
81
  - !ruby/object:Gem::Version
83
82
  version: '0'
84
- description:
85
- email:
86
83
  executables: []
87
84
  extensions: []
88
85
  extra_rdoc_files: []
89
86
  files:
90
- - lib/action_cable/subscription_adapters/async_cable_redis.rb
91
87
  - lib/async/cable.rb
92
88
  - lib/async/cable/middleware.rb
93
89
  - lib/async/cable/railtie.rb
@@ -96,13 +92,11 @@ files:
96
92
  - license.md
97
93
  - readme.md
98
94
  - releases.md
99
- homepage:
100
95
  licenses:
101
96
  - MIT
102
97
  metadata:
103
98
  documentation_uri: https://socketry.github.io/async-cable/
104
99
  source_code_uri: https://github.com/socketry/async-cable
105
- post_install_message:
106
100
  rdoc_options: []
107
101
  require_paths:
108
102
  - lib
@@ -110,15 +104,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
110
104
  requirements:
111
105
  - - ">="
112
106
  - !ruby/object:Gem::Version
113
- version: '3.1'
107
+ version: '3.2'
114
108
  required_rubygems_version: !ruby/object:Gem::Requirement
115
109
  requirements:
116
110
  - - ">="
117
111
  - !ruby/object:Gem::Version
118
112
  version: '0'
119
113
  requirements: []
120
- rubygems_version: 3.5.22
121
- signing_key:
114
+ rubygems_version: 3.6.7
122
115
  specification_version: 4
123
116
  summary: An asynchronous adapter for ActionCable.
124
117
  test_files: []
metadata.gz.sig CHANGED
Binary file
@@ -1,82 +0,0 @@
1
- # frozen_string_literal: true
2
- # Released under the MIT License.
3
- # Copyright, 2024, by Samuel Williams.
4
-
5
- require "action_cable/subscription_adapter/base"
6
- require "action_cable/subscription_adapter/channel_prefix"
7
- require "action_cable/subscription_adapter/subscriber_map"
8
-
9
- require "async/redis"
10
-
11
- module ActionCable::SubscriptionAdapter
12
- class AsyncCableRedis < Base
13
- prepend ChannelPrefix
14
-
15
- def initialize(*arguments, endpoint: nil, **options)
16
- super(*arguments, **options)
17
-
18
- @endpoint = endpoint || ::Async::Redis.local_endpoint
19
- @client = ::Async::Redis::Client.new(endpoint)
20
-
21
- @subscriber = Subscriber.new(@client, self.executor)
22
- end
23
-
24
- def subscribe(channel, callback, success_callback = nil)
25
- @subscriber.add_subscriber(channel, callback, success_callback)
26
- end
27
-
28
- def unsubscribe(channel, callback)
29
- @subscriber.remove_subscriber(channel, callback)
30
- end
31
-
32
- def broadcast(channel, payload)
33
- @client.publish(channel, payload)
34
- end
35
-
36
- def shutdown
37
- @subscriber&.close
38
- end
39
-
40
- private
41
-
42
- class Subscriber < SubscriberMap::Async
43
- CHANNEL = "_action_cable_internal"
44
-
45
- def initialize(client, executor, parent: Async::Task.current)
46
- super(executor)
47
-
48
- @context = @client.subscribe(CHANNEL)
49
- @task = parent.async{self.listen(CHANNEL)}
50
- end
51
-
52
- def add_channel(channel, on_success)
53
- @context.subscribe(channel)
54
- on_success&.call
55
- end
56
-
57
- def remove_channel(channel)
58
- @context.unsubscribe(channel)
59
- end
60
-
61
- def close
62
- if task = @task
63
- @task = nil
64
- task.stop
65
- end
66
-
67
- if context = @context
68
- @context = nil
69
- context.close
70
- end
71
- end
72
-
73
- private
74
-
75
- def listen
76
- context.each do |type, channel, message|
77
- self.broadcast(event[1], event[2])
78
- end
79
- end
80
- end
81
- end
82
- end