async-io 1.12.1 → 1.12.2

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: ebac6fa4a3e3537fc0fdcead5b43f10d62cff1230f69347942a35baaae853760
4
- data.tar.gz: 25fe69978444982daeefd3dd9793994f6d79b53d437f992b31425fdad48d6021
3
+ metadata.gz: '02688119fe7ef47b527495b74b5b60d5826de683dc4bc798b63f6c61ee962049'
4
+ data.tar.gz: c15e88f8b47470fe35b97ba674faaa20ac39f3cbab617a47523b66c516103125
5
5
  SHA512:
6
- metadata.gz: d57fd2561c7d365479be8a4721718ccccc68e5d4430ba738642c8460a22ff5f51230c4c30d2ac7668417a10cc758fedd5e1ddea17eb56408461fbba918f4a66c
7
- data.tar.gz: 276196bca0ab8a3fc7681e19d636a50169cebf9ffd97c1f39189d59a3f145d019d1b82982c35d4fc17c3d689c898fb52b5d5a678950fd176abe83e6889dd396d
6
+ metadata.gz: 224d6230ea743a3c4d5132222d4ef74c61362fa487c8da642ee470333be2cb8656604f5b4ccec4d28e0b799c22d13207c605ad1c4a53f2614e6cbc13c7d9ccf3
7
+ data.tar.gz: a129eceb200dc5171465d6b6f902efcf37d2c6b4d722c5ae1b82c716e66e78a77c8585742950482006a89fc86fc166ec6d83ce641eea09b7ef0e2ceefd7326f9
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
17
17
  spec.has_rdoc = "yard"
18
18
 
19
19
  spec.add_dependency "async", "~> 1.3"
20
- spec.add_development_dependency "async-rspec", "~> 1.4"
20
+ spec.add_development_dependency "async-rspec", "~> 1.6"
21
21
 
22
22
  spec.required_ruby_version = '~> 2.3'
23
23
 
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH << File.expand_path("../../lib", __dir__)
4
+
5
+ require 'async/reactor'
6
+ require 'async/io/stream'
7
+ require 'async/io/host_endpoint'
8
+ require 'async/io/protocol/line'
9
+
10
+ class User < Async::IO::Protocol::Line
11
+ end
12
+
13
+ endpoint = Async::IO::Endpoint.parse(ARGV.pop || "tcp://localhost:7138")
14
+
15
+ input = Async::IO::Protocol::Line.new(
16
+ Async::IO::Stream.new(
17
+ Async::IO::Generic.new($stdin)
18
+ )
19
+ )
20
+
21
+ Async::Reactor.run do |task|
22
+ socket = endpoint.connect
23
+ stream = Async::IO::Stream.new(socket)
24
+ user = User.new(stream)
25
+
26
+ connection = task.async do
27
+ while line = user.read_line
28
+ puts line
29
+ end
30
+ end
31
+
32
+ while line = input.read_line
33
+ user.write_lines line
34
+ end
35
+ rescue EOFError
36
+ # It's okay, we are disconnecting, because stdin has closed.
37
+ ensure
38
+ connection.stop
39
+ user.close
40
+ end
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH << File.expand_path("../../lib", __dir__)
4
+
5
+ require 'set'
6
+
7
+ require 'async/reactor'
8
+ require 'async/io/host_endpoint'
9
+ require 'async/io/protocol/line'
10
+
11
+ class User < Async::IO::Protocol::Line
12
+ attr_accessor :name
13
+
14
+ def login!
15
+ self.write_lines "Tell me your name, traveller:"
16
+ self.name = self.read_line
17
+ end
18
+
19
+ def to_s
20
+ @name || "unknown"
21
+ end
22
+ end
23
+
24
+ class Server
25
+ def initialize(endpoint)
26
+ @endpoint = endpoint
27
+ @users = Set.new
28
+ end
29
+
30
+ def broadcast(*message)
31
+ puts *message
32
+
33
+ @users.each do |user|
34
+ begin
35
+ user.write_lines(*message)
36
+ rescue EOFError
37
+ # In theory, it's possible this will fail if the remote end has disconnected. Each user has it's own task running `#connected`, and eventually `user.read_line` will fail. When it does, the disconnection logic will be invoked. A better way to do this would be to have a message queue, but for the sake of keeping this example simple, this is by far the better option.
38
+ end
39
+ end
40
+ end
41
+
42
+ def connected(user)
43
+ user.login!
44
+
45
+ broadcast("#{user} has joined")
46
+
47
+ user.write_lines("currently connected: #{@users.map(&:to_s).join(', ')}")
48
+
49
+ while message = user.read_line
50
+ broadcast("#{user.name}: #{message}")
51
+ end
52
+ rescue EOFError
53
+ # It's okay, client has disconnected.
54
+ ensure
55
+ disconnected(user)
56
+ end
57
+
58
+ def disconnected(user, reason = "quit")
59
+ @users.delete(user)
60
+
61
+ broadcast("#{user} has disconnected: #{reason}")
62
+ end
63
+
64
+ def run
65
+ Async::Reactor.run do |task|
66
+ @endpoint.accept do |peer|
67
+ stream = Async::IO::Stream.new(peer)
68
+ user = User.new(stream)
69
+
70
+ @users << user
71
+
72
+ connected(user)
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ endpoint = Async::IO::Endpoint.parse(ARGV.pop || "tcp://localhost:7138")
79
+ server = Server.new(endpoint)
80
+
81
+ server.run
@@ -24,7 +24,7 @@ module Async
24
24
  module IO
25
25
  module Protocol
26
26
  class Line
27
- def initialize(stream, eol = $\)
27
+ def initialize(stream, eol = $/)
28
28
  @stream = stream
29
29
  @eol = eol
30
30
  end
@@ -45,6 +45,8 @@ module Async
45
45
  @stream.write(@eol)
46
46
  end
47
47
  end
48
+
49
+ @stream.flush
48
50
  end
49
51
 
50
52
  def read_line
@@ -20,6 +20,6 @@
20
20
 
21
21
  module Async
22
22
  module IO
23
- VERSION = "1.12.1"
23
+ VERSION = "1.12.2"
24
24
  end
25
25
  end
@@ -23,12 +23,19 @@ require 'async/io/protocol/line'
23
23
  RSpec.describe Async::IO::Protocol::Line do
24
24
  let(:io) {StringIO.new}
25
25
  let(:stream) {Async::IO::Stream.new(io)}
26
- let(:protocol) {described_class.new(stream, "\n")}
26
+ subject {described_class.new(stream, "\n")}
27
+
28
+ context "default line ending" do
29
+ subject {described_class.new(stream)}
30
+
31
+ it "should have default eol terminator" do
32
+ expect(subject.eol).to_not be_nil
33
+ end
34
+ end
27
35
 
28
36
  describe '#write_lines' do
29
37
  it "should write line" do
30
- protocol.write_lines "Hello World"
31
- stream.flush
38
+ subject.write_lines "Hello World"
32
39
 
33
40
  expect(io.string).to be == "Hello World\n"
34
41
  end
@@ -41,11 +48,11 @@ RSpec.describe Async::IO::Protocol::Line do
41
48
  end
42
49
 
43
50
  it "should read one line" do
44
- expect(protocol.read_line).to be == "Hello World"
51
+ expect(subject.read_line).to be == "Hello World"
45
52
  end
46
53
 
47
54
  it "should be binary encoding" do
48
- expect(protocol.read_line.encoding).to be == Encoding::BINARY
55
+ expect(subject.read_line.encoding).to be == Encoding::BINARY
49
56
  end
50
57
  end
51
58
 
@@ -56,11 +63,11 @@ RSpec.describe Async::IO::Protocol::Line do
56
63
  end
57
64
 
58
65
  it "should read multiple lines" do
59
- expect(protocol.read_lines).to be == ["Hello", "World"]
66
+ expect(subject.read_lines).to be == ["Hello", "World"]
60
67
  end
61
68
 
62
69
  it "should be binary encoding" do
63
- expect(protocol.read_lines.first.encoding).to be == Encoding::BINARY
70
+ expect(subject.read_lines.first.encoding).to be == Encoding::BINARY
64
71
  end
65
72
  end
66
73
  end
@@ -50,6 +50,8 @@ RSpec.describe Async::IO::Stream do
50
50
  end
51
51
 
52
52
  describe '#read_until' do
53
+ include_context Async::RSpec::Memory
54
+
53
55
  it "can read a line" do
54
56
  io.write("hello\nworld\n")
55
57
  io.seek(0)
@@ -58,6 +60,15 @@ RSpec.describe Async::IO::Stream do
58
60
  expect(stream.read_until("\n")).to be == 'world'
59
61
  expect(stream.read_until("\n")).to be_nil
60
62
  end
63
+
64
+ it "minimises allocations" do
65
+ io.write("hello\nworld\n")
66
+ io.seek(0)
67
+
68
+ expect do
69
+ stream.read_until("\n")
70
+ end.to limit_allocations(String => 3)
71
+ end
61
72
  end
62
73
 
63
74
  describe '#flush' do
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.12.1
4
+ version: 1.12.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-22 00:00:00.000000000 Z
11
+ date: 2018-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.4'
33
+ version: '1.6'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.4'
40
+ version: '1.6'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -94,7 +94,9 @@ files:
94
94
  - README.md
95
95
  - Rakefile
96
96
  - async-io.gemspec
97
- - examples/broken_ssl.rb
97
+ - examples/chat/client.rb
98
+ - examples/chat/server.rb
99
+ - examples/issues/broken_ssl.rb
98
100
  - lib/async/io.rb
99
101
  - lib/async/io/address.rb
100
102
  - lib/async/io/address_endpoint.rb