async-dns 0.12.0 → 1.0.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
  SHA1:
3
- metadata.gz: 0302e920c59ef8d4ce72eaa34c0a442536304590
4
- data.tar.gz: eede22f4c518bfa0dcf094933083aeda33bc82a1
3
+ metadata.gz: a69c3e892e1022681eb81ec89cf6953b27f2dd65
4
+ data.tar.gz: f4b1bbfe1e36b9bae37681343c4eb1bc71f5b621
5
5
  SHA512:
6
- metadata.gz: 60687d211cdcee0afecee281daa5ae79322713b0adff0baf78f2c82ef700ebe99e056dc5f40d14a059f3a0d5a18c5741091b2a20cfe61bb8efd184b201c789a3
7
- data.tar.gz: '052292c7a58dcbfa650d902a7c7b15097fe1d7e1dd2b06ebda5d5009f68c7fc3ed130cbaeb36be26ee0a8f04b0099d7be080e028bcbe35016661e75c4d76f6cb'
6
+ metadata.gz: 0dc107b7e33810d8a45fdb660dfc7421ad95383d8e14db6006175a335b0cc80500065e2c78c3d80ef53291a2ae8f3617a5cdb081475009ddff5c0edf3ff06576
7
+ data.tar.gz: 3209d74dc8a3ae956acb687da50ac5049f5c5a4be820ae8e5f1ca88c3c02b1bcd077e02ba33a23a498d90f8cd86b2ad52b2582907c734ccfee45f4372487cb42
data/.rspec CHANGED
@@ -1,4 +1,3 @@
1
- --color
2
1
  --format documentation
3
2
  --warnings
4
3
  --require spec_helper
@@ -6,14 +6,17 @@ addons:
6
6
  apt:
7
7
  packages:
8
8
  - bind9
9
- rvm:
10
- - 2.1
11
- - 2.2
12
- - 2.3
13
- - 2.4
14
- - ruby-head
15
- - jruby-head
9
+
16
10
  matrix:
11
+ include:
12
+ - rvm: 2.1
13
+ - rvm: 2.2
14
+ - rvm: 2.3
15
+ - rvm: 2.4
16
+ - rvm: ruby-head
17
+ - rvm: jruby-head
18
+ env:
19
+ - JRUBY_OPTS="--debug -X+O"
17
20
  allow_failures:
18
21
  - rvm: ruby-head
19
- - rvm: jruby-head
22
+ - rvm: jruby-head
data/Gemfile CHANGED
@@ -7,6 +7,12 @@ group :development do
7
7
  end
8
8
 
9
9
  group :test do
10
+ gem 'ruby-prof', platforms: [:mri]
11
+ gem "benchmark-ips"
12
+
10
13
  gem 'simplecov'
11
14
  gem 'coveralls', require: false
15
+
16
+ # For comparisons:
17
+ gem "nokogiri"
12
18
  end
data/README.md CHANGED
@@ -28,6 +28,7 @@ Or install it yourself as:
28
28
 
29
29
  Here is a simple example showing how to use the resolver:
30
30
 
31
+ ```ruby
31
32
  Async::Reactor.run do
32
33
  resolver = Async::DNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
33
34
 
@@ -36,11 +37,13 @@ Here is a simple example showing how to use the resolver:
36
37
  puts addresses.inspect
37
38
  end
38
39
  => [#<Resolv::IPv4 202.124.127.240>, #<Resolv::IPv4 202.124.127.216>, #<Resolv::IPv4 202.124.127.223>, #<Resolv::IPv4 202.124.127.227>, #<Resolv::IPv4 202.124.127.234>, #<Resolv::IPv4 202.124.127.230>, #<Resolv::IPv4 202.124.127.208>, #<Resolv::IPv4 202.124.127.249>, #<Resolv::IPv4 202.124.127.219>, #<Resolv::IPv4 202.124.127.218>, #<Resolv::IPv4 202.124.127.212>, #<Resolv::IPv4 202.124.127.241>, #<Resolv::IPv4 202.124.127.238>, #<Resolv::IPv4 202.124.127.245>, #<Resolv::IPv4 202.124.127.251>, #<Resolv::IPv4 202.124.127.229>]
40
+ ```
39
41
 
40
42
  ### Server
41
43
 
42
44
  Here is a simple example showing how to use the server:
43
45
 
46
+ ```ruby
44
47
  require 'async/dns'
45
48
 
46
49
  class TestServer < Async::DNS::Server
@@ -51,9 +54,10 @@ Here is a simple example showing how to use the server:
51
54
  end
52
55
  end
53
56
 
54
- server = TestServer.new(listen: [[:udp, '127.0.0.1', 2346]])
57
+ server = TestServer.new([[:udp, '127.0.0.1', 2346]])
55
58
 
56
59
  server.run
60
+ ```
57
61
 
58
62
  Then to test you could use `dig` like so:
59
63
 
data/Rakefile CHANGED
@@ -24,7 +24,7 @@ task :server do
24
24
  end
25
25
  end
26
26
 
27
- server = TestServer.new(listen: [[:udp, '127.0.0.1', 2346]])
27
+ server = TestServer.new([[:udp, '127.0.0.1', 2346]])
28
28
 
29
29
  Async::Reactor.run do
30
30
  server.run
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
21
21
  spec.require_paths = ["lib"]
22
22
  spec.has_rdoc = "yard"
23
23
 
24
- spec.add_dependency("async-io", "~> 0.1")
24
+ spec.add_dependency("async-io", "~> 1.0")
25
25
 
26
26
  spec.add_development_dependency "async-rspec", "~> 1.0"
27
27
  spec.add_development_dependency "process-daemon", "~> 1.0"
@@ -22,15 +22,15 @@ require_relative 'transport'
22
22
 
23
23
  module Async::DNS
24
24
  class GenericHandler
25
- def initialize(server, address)
25
+ def initialize(server, endpoint)
26
26
  @server = server
27
- @address = address
27
+ @endpoint = endpoint
28
28
 
29
29
  @logger = @server.logger || Async.logger
30
30
  end
31
31
 
32
32
  attr :server
33
- attr :address
33
+ attr :endpoint
34
34
 
35
35
  def error_response(query = nil, code = Resolv::DNS::RCode::ServFail)
36
36
  # Encoding may fail, so we need to handle this particular case:
@@ -68,7 +68,7 @@ module Async::DNS
68
68
  # Handling incoming UDP requests, which are single data packets, and pass them on to the given server.
69
69
  class DatagramHandler < GenericHandler
70
70
  def run(task: Async::Task.current)
71
- @address.bind do |socket|
71
+ @endpoint.bind do |socket|
72
72
  while true
73
73
  Async.logger.debug(self.class.name) {"-> socket.recvfrom"}
74
74
  input_data, remote_address = socket.recvmsg(UDP_TRUNCATION_SIZE)
@@ -110,7 +110,7 @@ module Async::DNS
110
110
 
111
111
  class StreamHandler < GenericHandler
112
112
  def run(task: Async::Task.current)
113
- @address.accept do |client, address|
113
+ @endpoint.accept do |client, address|
114
114
  handle_connection(client)
115
115
  end
116
116
  end
@@ -24,7 +24,7 @@ require 'resolv-replace'
24
24
  module Async::DNS
25
25
  module Replace
26
26
  class << self
27
- attr :resolver, true
27
+ attr_accessor :resolver
28
28
 
29
29
  def resolver?
30
30
  resolver != nil
@@ -46,8 +46,8 @@ module Async::DNS
46
46
  # Servers are specified in the same manor as options[:listen], e.g.
47
47
  # [:tcp/:udp, address, port]
48
48
  # In the case of multiple servers, they will be checked in sequence.
49
- def initialize(servers, origin: nil, logger: Async.logger, timeout: DEFAULT_TIMEOUT)
50
- @servers = servers
49
+ def initialize(endpoints, origin: nil, logger: Async.logger, timeout: DEFAULT_TIMEOUT)
50
+ @endpoints = endpoints
51
51
 
52
52
  @origin = origin
53
53
  @logger = logger
@@ -97,14 +97,14 @@ module Async::DNS
97
97
  retries = options.fetch(:retries, DEFAULT_RETRIES)
98
98
  delay = options.fetch(:delay, DEFAULT_DELAY)
99
99
 
100
- records = lookup(name, resource_class, cache) do |name, resource_class|
100
+ records = lookup(name, resource_class, cache) do |lookup_name, lookup_resource_class|
101
101
  response = nil
102
102
 
103
103
  retries.times do |i|
104
104
  # Wait 10ms before trying again:
105
105
  sleep delay if delay and i > 0
106
106
 
107
- response = query(name, resource_class)
107
+ response = query(lookup_name, lookup_resource_class)
108
108
 
109
109
  break if response
110
110
  end
@@ -134,18 +134,18 @@ module Async::DNS
134
134
 
135
135
  # Send the message to available servers. If no servers respond correctly, nil is returned. This result indicates a failure of the resolver to correctly contact any server and get a valid response.
136
136
  def dispatch_request(message, task: Async::Task.current)
137
- request = Request.new(message, @servers)
137
+ request = Request.new(message, @endpoints)
138
138
 
139
- request.each do |address|
140
- @logger.debug "[#{message.id}] Sending request #{message.question.inspect} to address #{address.inspect}" if @logger
139
+ request.each do |endpoint|
140
+ @logger.debug "[#{message.id}] Sending request #{message.question.inspect} to address #{endpoint.inspect}" if @logger
141
141
 
142
142
  begin
143
143
  response = nil
144
144
 
145
145
  task.timeout(@timeout) do
146
- @logger.debug "[#{message.id}] -> Try address #{address}" if @logger
147
- response = try_server(request, address)
148
- @logger.debug "[#{message.id}] <- Try address #{address} = #{response}" if @logger
146
+ @logger.debug "[#{message.id}] -> Try address #{endpoint}" if @logger
147
+ response = try_server(request, endpoint)
148
+ @logger.debug "[#{message.id}] <- Try address #{endpoint} = #{response}" if @logger
149
149
  end
150
150
 
151
151
  if valid_response(message, response)
@@ -175,8 +175,8 @@ module Async::DNS
175
175
  response = yield(name, resource_class)
176
176
 
177
177
  if response
178
- response.answer.each do |name, ttl, record|
179
- (records[name] ||= []) << record
178
+ response.answer.each do |name_in_answer, ttl, record|
179
+ (records[name_in_answer] ||= []) << record
180
180
  end
181
181
  end
182
182
 
@@ -184,14 +184,14 @@ module Async::DNS
184
184
  end
185
185
  end
186
186
 
187
- def try_server(request, address)
188
- case address.type
187
+ def try_server(request, endpoint)
188
+ case endpoint.socket_type
189
189
  when Socket::SOCK_DGRAM
190
- try_datagram_server(request, address)
190
+ try_datagram_server(request, endpoint)
191
191
  when Socket::SOCK_STREAM
192
- try_stream_server(request, address)
192
+ try_stream_server(request, endpoint)
193
193
  else
194
- raise InvalidProtocolError.new(address)
194
+ raise InvalidProtocolError.new(endpoint)
195
195
  end
196
196
  end
197
197
 
@@ -209,8 +209,8 @@ module Async::DNS
209
209
  return false
210
210
  end
211
211
 
212
- def try_datagram_server(request, address, task: Async::Task.current)
213
- address.connect do |socket|
212
+ def try_datagram_server(request, endpoint, task: Async::Task.current)
213
+ endpoint.connect do |socket|
214
214
  socket.sendmsg(request.packet, 0)
215
215
 
216
216
  data, peer = socket.recvmsg(UDP_TRUNCATION_SIZE)
@@ -219,10 +219,10 @@ module Async::DNS
219
219
  end
220
220
  end
221
221
 
222
- def try_stream_server(request, address)
222
+ def try_stream_server(request, endpoint)
223
223
  context = Async::Task.current
224
224
 
225
- address.connect do |socket|
225
+ endpoint.connect do |socket|
226
226
  StreamTransport.write_chunk(socket, request.packet)
227
227
 
228
228
  input_data = StreamTransport.read_chunk(socket)
@@ -233,15 +233,15 @@ module Async::DNS
233
233
 
234
234
  # Manages a single DNS question message across one or more servers.
235
235
  class Request
236
- def initialize(message, servers)
236
+ def initialize(message, endpoints)
237
237
  @message = message
238
238
  @packet = message.encode
239
239
 
240
- @servers = servers.dup
240
+ @endpoints = endpoints.dup
241
241
 
242
242
  # We select the protocol based on the size of the data:
243
243
  if @packet.bytesize > UDP_TRUNCATION_SIZE
244
- @servers.delete_if{|server| server[0] == :udp}
244
+ @endpoints.delete_if{|server| server[0] == :udp}
245
245
  end
246
246
  end
247
247
 
@@ -250,7 +250,7 @@ module Async::DNS
250
250
  attr :logger
251
251
 
252
252
  def each(&block)
253
- Async::IO::Address.each(@servers, &block)
253
+ Async::IO::Endpoint.each(@endpoints, &block)
254
254
  end
255
255
 
256
256
  def update_id!(id)
@@ -19,7 +19,7 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  require 'async'
22
- require 'async/io/address'
22
+ require 'async/io/endpoint'
23
23
 
24
24
  require_relative 'transaction'
25
25
  require_relative 'logger'
@@ -27,7 +27,7 @@ require_relative 'logger'
27
27
  module Async::DNS
28
28
  class Server
29
29
  # The default server interfaces
30
- DEFAULT_INTERFACES = [[:udp, "0.0.0.0", 53], [:tcp, "0.0.0.0", 53]]
30
+ DEFAULT_ENDPOINTS = [[:udp, "0.0.0.0", 53], [:tcp, "0.0.0.0", 53]]
31
31
 
32
32
  # Instantiate a server with a block
33
33
  #
@@ -37,8 +37,8 @@ module Async::DNS
37
37
  # end
38
38
  # end
39
39
  #
40
- def initialize(listen: DEFAULT_INTERFACES, origin: '.', logger: Async.logger)
41
- @interfaces = listen
40
+ def initialize(endpoints = DEFAULT_ENDPOINTS, origin: '.', logger: Async.logger)
41
+ @endpoints = endpoints
42
42
  @origin = origin
43
43
  @logger = logger
44
44
 
@@ -124,14 +124,14 @@ module Async::DNS
124
124
  def setup_handlers
125
125
  fire(:setup)
126
126
 
127
- Async::IO::Address.each(@interfaces) do |address|
128
- case address.type
127
+ Async::IO::Endpoint.each(@endpoints) do |endpoint|
128
+ case endpoint.socket_type
129
129
  when Socket::SOCK_DGRAM
130
- @logger.info "<> Listening for datagrams on #{address.inspect}"
131
- @handlers << DatagramHandler.new(self, address)
130
+ @logger.info "<> Listening for datagrams on #{endpoint.inspect}"
131
+ @handlers << DatagramHandler.new(self, endpoint)
132
132
  when Socket::SOCK_STREAM
133
- @logger.info "<> Listening for connections on #{address.inspect}"
134
- @handlers << StreamHandler.new(self, address)
133
+ @logger.info "<> Listening for connections on #{endpoint.inspect}"
134
+ @handlers << StreamHandler.new(self, endpoint)
135
135
  else
136
136
  raise ArgumentError.new("Don't know how to handle #{address}")
137
137
  end
@@ -20,6 +20,6 @@
20
20
 
21
21
  module Async
22
22
  module DNS
23
- VERSION = '0.12.0'
23
+ VERSION = '1.0.0'
24
24
  end
25
25
  end
@@ -25,7 +25,7 @@ describe Async::DNS::StreamHandler do
25
25
  include_context Async::RSpec::Reactor
26
26
 
27
27
  let(:server) {Async::DNS::Server.new}
28
- let(:address) {Async::IO::Address.tcp('127.0.0.1', 6666)}
28
+ let(:address) {Async::IO::Endpoint.tcp('127.0.0.1', 6666)}
29
29
 
30
30
  subject {described_class.new(server, address)}
31
31
 
@@ -44,7 +44,7 @@ describe Async::DNS::DatagramHandler do
44
44
  include_context Async::RSpec::Reactor
45
45
 
46
46
  let(:server) {Async::DNS::Server.new}
47
- let(:address) {Async::IO::Address.udp('127.0.0.1', 6666)}
47
+ let(:address) {Async::IO::Endpoint.udp('127.0.0.1', 6666)}
48
48
 
49
49
  subject {described_class.new(server, address)}
50
50
 
@@ -38,7 +38,7 @@ module Async::DNS::IPv6Spec
38
38
  include_context Async::RSpec::Reactor
39
39
 
40
40
  let(:server_interfaces) {[[:tcp, '::', 2004]]}
41
- let(:server) {TestServer.new(listen: server_interfaces)}
41
+ let(:server) {TestServer.new(server_interfaces)}
42
42
 
43
43
  it "should connect to the server using TCP via IPv6" do
44
44
  task = server.run
@@ -59,7 +59,7 @@ module Async::DNS::IPv6Spec
59
59
  include_context Async::RSpec::Reactor
60
60
 
61
61
  let(:server_interfaces) {[[:udp, '::', 2006]]}
62
- let(:server) {TestServer.new(listen: server_interfaces)}
62
+ let(:server) {TestServer.new(server_interfaces)}
63
63
 
64
64
  it "should connect to the server using UDP via IPv6" do
65
65
  task = server.run
@@ -25,28 +25,49 @@ require 'benchmark'
25
25
  require 'process/daemon'
26
26
 
27
27
  module Async::DNS::ServerPerformanceSpec
28
- describe Async::DNS::Server do
29
- include_context Async::RSpec::Reactor
28
+ class MillionServer < Async::DNS::Server
29
+ def initialize(*)
30
+ super
31
+
32
+ @domains = {}
33
+
34
+ (1..5_000).each do |i|
35
+ domain = "domain#{i}.local"
36
+
37
+ @domains[domain] = "#{69}.#{(i >> 16)%256}.#{(i >> 8)%256}.#{i%256}"
38
+ end
39
+ end
30
40
 
31
- context 'benchmark' do
32
- class MillionServer < Async::DNS::Server
33
- def initialize(*)
34
- super
35
-
36
- @million = {}
37
-
38
- (1..5_000).each do |i|
39
- domain = "domain#{i}.local"
41
+ attr :domains
42
+
43
+ def process(name, resource_class, transaction)
44
+ transaction.respond!(@domains[name])
45
+ end
46
+ end
40
47
 
41
- @million[domain] = "#{69}.#{(i >> 16)%256}.#{(i >> 8)%256}.#{i%256}"
42
- end
43
- end
44
-
45
- def process(name, resource_class, transaction)
46
- transaction.respond!(@million[name])
47
- end
48
+ RSpec.describe MillionServer do
49
+ # include_context "profile"
50
+ include_context Async::RSpec::Reactor
51
+
52
+ let(:interfaces) {[[:udp, '127.0.0.1', 8899]]}
53
+ let(:server) {MillionServer.new(interfaces)}
54
+ let(:resolver) {Async::DNS::Resolver.new(interfaces)}
55
+
56
+ it "should be fast" do
57
+ task = server.run
58
+
59
+ server.domains.each do |name, address|
60
+ resolved = resolver.addresses_for(name)
48
61
  end
49
62
 
63
+ task.stop
64
+ end
65
+ end
66
+
67
+ RSpec.describe Async::DNS::Server do
68
+ include_context Async::RSpec::Reactor
69
+
70
+ context 'benchmark' do
50
71
  class AsyncServerDaemon < Process::Daemon
51
72
  def working_directory
52
73
  File.expand_path("../tmp", __FILE__)
@@ -58,7 +79,7 @@ module Async::DNS::ServerPerformanceSpec
58
79
 
59
80
  def startup
60
81
  puts "Starting DNS server..."
61
- @server = MillionServer.new(listen: [[:udp, '0.0.0.0', 5300]])
82
+ @server = MillionServer.new([[:udp, '0.0.0.0', 5300]])
62
83
 
63
84
  reactor.async do
64
85
  @task = @server.run
@@ -121,13 +142,15 @@ module Async::DNS::ServerPerformanceSpec
121
142
  resolver = Async::DNS::Resolver.new([[:udp, '127.0.0.1', port]])
122
143
 
123
144
  x.report(name) do
124
- # Number of requests remaining since this is an asynchronous event loop:
125
- 5.times do
126
- pending = @domains.size
127
-
128
- resolved = @domains.collect{|domain| resolver.addresses_for(domain)}
145
+ Async::Reactor.run do
146
+ # Number of requests remaining since this is an asynchronous event loop:
147
+ 5.times do
148
+ pending = @domains.size
129
149
 
130
- expect(resolved).to_not include(nil)
150
+ resolved = @domains.collect{|domain| resolver.addresses_for(domain)}
151
+
152
+ expect(resolved).to_not include(nil)
153
+ end
131
154
  end
132
155
  end
133
156
  end
@@ -39,7 +39,7 @@ module Async::DNS::SlowServerSpec
39
39
  include_context Async::RSpec::Reactor
40
40
 
41
41
  let(:server_interfaces) {[[:udp, '0.0.0.0', 5330], [:tcp, '0.0.0.0', 5330]]}
42
- let(:server) {SlowServer.new(listen: server_interfaces)}
42
+ let(:server) {SlowServer.new(server_interfaces)}
43
43
 
44
44
  around(:each) do |example|
45
45
  begin
@@ -38,7 +38,7 @@ module Async::DNS::SocketSpec
38
38
  include_context Async::RSpec::Reactor
39
39
 
40
40
  let(:server_interfaces) {[TCPServer.new('127.0.0.1', 2002)]}
41
- let(:server) {TestServer.new(listen: server_interfaces)}
41
+ let(:server) {TestServer.new(server_interfaces)}
42
42
 
43
43
  it "should create server with existing TCP socket" do
44
44
  task = server.run
@@ -56,7 +56,7 @@ module Async::DNS::SocketSpec
56
56
  include_context Async::RSpec::Reactor
57
57
 
58
58
  let(:server_interfaces) {[UDPSocket.new.tap{|socket| socket.bind('127.0.0.1', 2002)}]}
59
- let(:server) {TestServer.new(listen: server_interfaces)}
59
+ let(:server) {TestServer.new(server_interfaces)}
60
60
 
61
61
  it "should create server with existing UDP socket" do
62
62
  task = server.run
@@ -42,7 +42,7 @@ module Async::DNS::TruncationSpec
42
42
  describe "Async::DNS Truncation Server" do
43
43
  include_context Async::RSpec::Reactor
44
44
 
45
- let(:server) {TestServer.new(listen: SERVER_PORTS)}
45
+ let(:server) {TestServer.new(SERVER_PORTS)}
46
46
 
47
47
  it "should use tcp because of large response" do
48
48
  task = server.run
@@ -26,7 +26,26 @@ require "bundler/setup"
26
26
  require "async/rspec"
27
27
  require "async/dns"
28
28
 
29
- # abort "Warning, ulimit is too low!" if `ulimit -n`.to_i < 10000
29
+ begin
30
+ require 'ruby-prof'
31
+
32
+ RSpec.shared_context "profile" do
33
+ around(:each) do |example|
34
+ profile = RubyProf.profile(merge_fibers: true) do
35
+ example.run
36
+ end
37
+
38
+ printer = RubyProf::FlatPrinter.new(profile)
39
+ printer.print(STDOUT)
40
+ end
41
+ end
42
+ rescue LoadError
43
+ RSpec.shared_context "profile" do
44
+ before(:all) do
45
+ puts "Profiling not supported on this platform."
46
+ end
47
+ end
48
+ end
30
49
 
31
50
  RSpec.configure do |config|
32
51
  # Enable flags like --only-failures and --next-failure
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-dns
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 1.0.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: 2017-05-25 00:00:00.000000000 Z
11
+ date: 2017-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async-io
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.1'
19
+ version: '1.0'
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: '0.1'
26
+ version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: async-rspec
29
29
  requirement: !ruby/object:Gem::Requirement