async-io 1.18.5 → 1.20.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4521c94506778f0d7e6f5dec2fe76bf6b6f0374ae3c327e29775063bd3393aaa
4
- data.tar.gz: 56d1f0388b1d1a64a87dbb5086bcbd209602933ab805fae44ea6e699cc3eba8b
3
+ metadata.gz: 69adfd1cd876361c3b94bc80a5f5c164d45df0156a37c6f9fc54542a79bc443c
4
+ data.tar.gz: 32758166362e4780b7d251d4f649cdc2eb14fd4ab48a378be94968c5719053df
5
5
  SHA512:
6
- metadata.gz: 7c84cb8f453e9b7c7f80af18443d04eaeca38e46172afbc1ec4f6c219123449a5b8744d72db0c282e2d3da8826f29aa64f331698608a589c9c35a761bc6531f4
7
- data.tar.gz: 027bf4fc6e910b3e1fdf883f7aa6a98045131f43318a014f77bb6e1734d9e932f95bd54fb23b9237e9ef78bccb1f70fc52c424ece21020e31663ea3a6b151ffe
6
+ metadata.gz: 9fc9a5d6e563b8dbe9b2c700ce284ae905efb90a338b79ebed4daff5368912707355fe40efcbda243948e061bd0b143cd8e4bf22bf232dbc9afcf9d93aa5356b
7
+ data.tar.gz: 94d7271c1c6e50a84c3120ae408989b2caeab045a8b07e54d417d4bc6159eea35138cc20cc86ba879d4492e457aee75eaa078ad23d2826c80c21fa12ed24d128
data/Gemfile CHANGED
@@ -12,7 +12,5 @@ group :test do
12
12
  gem 'benchmark-ips'
13
13
  gem 'ruby-prof', platforms: :mri
14
14
 
15
- gem 'async-container'
16
-
17
15
  gem 'http'
18
16
  end
@@ -19,7 +19,9 @@ Gem::Specification.new do |spec|
19
19
  spec.add_development_dependency "async-rspec", "~> 1.10"
20
20
 
21
21
  spec.required_ruby_version = '~> 2.3'
22
-
22
+
23
+ spec.add_development_dependency "async-container", "~> 0.10.0"
24
+
23
25
  spec.add_development_dependency "bundler"
24
26
  spec.add_development_dependency "covered"
25
27
  spec.add_development_dependency "rake", "~> 10.0"
@@ -20,7 +20,9 @@ puts "Starting #{CONCURRENCY} processes, running #{TASKS} tasks, making #{REPEAT
20
20
  puts "Total number of connections: #{CONCURRENCY * TASKS * REPEATS}!"
21
21
 
22
22
  begin
23
- container = Async::Container::Forked.new(concurrency: CONCURRENCY) do
23
+ container = Async::Container::Forked.new
24
+
25
+ container.run(count: CONCURRENCY) do
24
26
  Async do |task|
25
27
  connections = []
26
28
 
@@ -28,7 +28,6 @@ module Async
28
28
  super(**options)
29
29
 
30
30
  @address = address
31
- @options = options
32
31
  end
33
32
 
34
33
  def to_s
@@ -36,7 +35,6 @@ module Async
36
35
  end
37
36
 
38
37
  attr :address
39
- attr :options
40
38
 
41
39
  # Bind a socket to the given address. If a block is given, the socket will be automatically closed when the block exits.
42
40
  # @yield [Socket] the bound socket
@@ -51,11 +49,5 @@ module Async
51
49
  Socket.connect(@address, **@options, &block)
52
50
  end
53
51
  end
54
-
55
- class Endpoint
56
- def self.unix(*args, **options)
57
- AddressEndpoint.new(Address.unix(*args), **options)
58
- end
59
- end
60
52
  end
61
53
  end
@@ -50,10 +50,13 @@ module Async
50
50
  when 0, Socket::IPPROTO_TCP
51
51
  self.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, value ? 1 : 0)
52
52
  else
53
- warn "Unsure how to sync=#{value} for #{self.protocol}!"
53
+ Async.logger.warn(self) {"Unsure how to sync=#{value} for #{self.protocol}!"}
54
54
  end
55
55
  rescue Errno::EINVAL
56
56
  # On Darwin, sometimes occurs when the connection is not yet fully formed. Empirically, TCP_NODELAY is enabled despite this result.
57
+ rescue Errno::EOPNOTSUPP
58
+ # Some platforms may simply not support the operation.
59
+ Async.logger.warn(self) {"Unable to set sync=#{value}!"}
57
60
  end
58
61
 
59
62
  def sync
@@ -138,6 +141,7 @@ module Async
138
141
  alias accept_nonblock accept
139
142
  alias sysaccept accept
140
143
 
144
+ # Build and wrap the underlying io.
141
145
  def self.build(*args, timeout: nil, task: Task.current)
142
146
  socket = wrapped_klass.new(*args)
143
147
 
@@ -0,0 +1,67 @@
1
+ # Copyright, 2019, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative 'address_endpoint'
22
+
23
+ module Async
24
+ module IO
25
+ # This class doesn't exert ownership over the specified unix socket and ensures exclusive access by using `flock` where possible.
26
+ class UNIXEndpoint < AddressEndpoint
27
+ def initialize(path, type, **options)
28
+ # I wonder if we should implement chdir behaviour in here if path is longer than 104 characters.
29
+ super(Address.unix(path, type), **options)
30
+
31
+ @path = path
32
+ end
33
+
34
+ def to_s
35
+ "\#<#{self.class} #{@path.inspect}>"
36
+ end
37
+
38
+ attr :path
39
+
40
+ def bound?
41
+ self.connect do
42
+ return true
43
+ end
44
+ rescue Errno::ECONNREFUSED
45
+ return false
46
+ end
47
+
48
+ def bind(&block)
49
+ Socket.bind(@address, **@options, &block)
50
+ rescue Errno::EADDRINUSE
51
+ # If you encounter EADDRINUSE from `bind()`, you can check if the socket is actually accepting connections by attempting to `connect()` to it. If the socket is still bound by an active process, the connection will succeed. Otherwise, it should be safe to `unlink()` the path and try again.
52
+ if !bound? && File.exist?(@path)
53
+ File.unlink(@path)
54
+ retry
55
+ else
56
+ raise
57
+ end
58
+ end
59
+ end
60
+
61
+ class Endpoint
62
+ def self.unix(path, type = ::Socket::SOCK_STREAM, **options)
63
+ UNIXEndpoint.new(path, type, **options)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -20,6 +20,6 @@
20
20
 
21
21
  module Async
22
22
  module IO
23
- VERSION = "1.18.5"
23
+ VERSION = "1.20.0"
24
24
  end
25
25
  end
@@ -41,21 +41,26 @@ RSpec.shared_examples_for Async::IO::SharedEndpoint do |container_class|
41
41
  end.wait
42
42
  end
43
43
 
44
+ let(:container) {container_class.new}
45
+
44
46
  it "can use bound endpoint in container" do
45
- container = container_class.new(concurrency: 1) do
47
+ container.run(count: 1) do
46
48
  bound_endpoint.accept do |peer|
47
49
  peer.write "Hello World"
48
50
  peer.close
49
51
  end
50
52
  end
51
53
 
52
- Async do
53
- client_endpoint.connect do |peer|
54
- expect(peer.read(11)).to eq "Hello World"
54
+ container.wait do
55
+ Async do
56
+ client_endpoint.connect do |peer|
57
+ expect(peer.read(11)).to eq "Hello World"
58
+ end
55
59
  end
60
+
61
+ container.stop(false)
56
62
  end
57
63
 
58
- container.stop
59
64
  bound_endpoint.close
60
65
  end
61
66
  end
@@ -0,0 +1,78 @@
1
+ # Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'async/io/unix_endpoint'
22
+
23
+ RSpec.describe Async::IO::UNIXEndpoint do
24
+ include_context Async::RSpec::Reactor
25
+
26
+ let(:data) {"The quick brown fox jumped over the lazy dog."}
27
+ let(:path) {File.join(__dir__, "unix-socket")}
28
+ subject {described_class.unix(path)}
29
+
30
+ before(:each) do
31
+ FileUtils.rm_f path
32
+ end
33
+
34
+ after do
35
+ FileUtils.rm_f path
36
+ end
37
+
38
+ it "should echo data back to peer" do
39
+ server_task = reactor.async do
40
+ subject.accept do |peer|
41
+ peer.send(peer.recv(512))
42
+ end
43
+ end
44
+
45
+ reactor.async do
46
+ subject.connect do |client|
47
+ client.send(data)
48
+
49
+ response = client.recv(512)
50
+
51
+ expect(response).to be == data
52
+ end
53
+ end.wait
54
+
55
+ server_task.stop
56
+ end
57
+
58
+ it "should fails to bind if there is an existing binding" do
59
+ condition = Async::Condition.new
60
+
61
+ reactor.async do
62
+ condition.wait
63
+
64
+ expect do
65
+ subject.bind
66
+ end.to raise_error(Errno::EADDRINUSE)
67
+ end
68
+
69
+ server_task = reactor.async do
70
+ subject.bind do |server|
71
+ server.listen(1)
72
+ condition.signal
73
+ end
74
+ end
75
+
76
+ server_task.stop
77
+ end
78
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-io
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.18.5
4
+ version: 1.20.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-24 00:00:00.000000000 Z
11
+ date: 2019-03-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.10'
41
+ - !ruby/object:Gem::Dependency
42
+ name: async-container
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.10.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.10.0
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -139,6 +153,7 @@ files:
139
153
  - lib/async/io/tcp_socket.rb
140
154
  - lib/async/io/trap.rb
141
155
  - lib/async/io/udp_socket.rb
156
+ - lib/async/io/unix_endpoint.rb
142
157
  - lib/async/io/unix_socket.rb
143
158
  - lib/async/io/version.rb
144
159
  - spec/addrinfo.rb
@@ -162,6 +177,7 @@ files:
162
177
  - spec/async/io/tcp_socket_spec.rb
163
178
  - spec/async/io/trap_spec.rb
164
179
  - spec/async/io/udp_socket_spec.rb
180
+ - spec/async/io/unix_endpoint_spec.rb
165
181
  - spec/async/io/unix_socket_spec.rb
166
182
  - spec/async/io/wrap/http_rb_spec.rb
167
183
  - spec/async/io/wrap/tcp_spec.rb
@@ -211,6 +227,7 @@ test_files:
211
227
  - spec/async/io/tcp_socket_spec.rb
212
228
  - spec/async/io/trap_spec.rb
213
229
  - spec/async/io/udp_socket_spec.rb
230
+ - spec/async/io/unix_endpoint_spec.rb
214
231
  - spec/async/io/unix_socket_spec.rb
215
232
  - spec/async/io/wrap/http_rb_spec.rb
216
233
  - spec/async/io/wrap/tcp_spec.rb