async-io 1.12.1 → 1.12.2

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: 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