async-http 0.31.1 → 0.32.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: 20c4728c088a68663d0f336b2326d3e988a342c5d1f1cd2890a12e43cefda133
4
- data.tar.gz: da0503f98a16003b0a2c6606e4419ebb311365dac4be7ea685b18bb994b3613c
3
+ metadata.gz: a35d727fb4d1811ad0ddea60170aef62f60084759c1c2d0f658e335f3496be4d
4
+ data.tar.gz: 58004aea432052f2979346a359ad55f2d098f9fa1d9f03e4f89bd08474ced951
5
5
  SHA512:
6
- metadata.gz: 5ecdd9b68abcaf50db65f02ab8f1db4e8ce1e4a00af980510df5d1323a0d4c3b2c135d85fe3683dcf02f5e818b364fe659c44ab5df25459b687ba2a50d8db9e2
7
- data.tar.gz: 68536e0f1ea03914f0e4b34116e7a7f738c5fbc7cf2baf9f2d87f7dd6675329c6c48b444ece69cf8a977f4184a525df1fc14b25bb3f7cb3a85c4983519551eed
6
+ metadata.gz: cee0898153224018a6d9a6b04b5da0635895c59aeb3f37fe5ee3fa20260529a887ee73398afa34ec98ab443a5699d0506bf40fab54123705c1f336ff7e381d72
7
+ data.tar.gz: fb39c47f2edb32732b16d8a8ac3cd8158f6f78212d4dae6af2201eedc24b6bdf30085a1670b4040fb23f384b51efdf9fcaa4b09994a25c86004da9672a4104e2
@@ -20,3 +20,20 @@
20
20
 
21
21
  require_relative 'body/writable'
22
22
  require_relative 'body/buffered'
23
+
24
+ module Async
25
+ module HTTP
26
+ # These classes implement a general IO model for streaming HTTP bodies.
27
+ module Body
28
+ # The implementation assumes a sequential unbuffered stream of data.
29
+ # class Body
30
+ # def each -> yield(String | nil)
31
+ # def read -> String | nil
32
+ # def join -> String
33
+
34
+ # def finish -> buffer the stream and close it.
35
+ # def close(error = nil) -> close the stream immediately.
36
+ # end
37
+ end
38
+ end
39
+ end
@@ -54,6 +54,10 @@ module Async
54
54
  @index = 0
55
55
  end
56
56
 
57
+ def finish
58
+ self
59
+ end
60
+
57
61
  def length
58
62
  @length ||= @chunks.inject(0) {|sum, chunk| sum + chunk.bytesize}
59
63
  end
@@ -62,10 +66,6 @@ module Async
62
66
  @index >= @chunks.length
63
67
  end
64
68
 
65
- def close
66
- self
67
- end
68
-
69
69
  def read
70
70
  if chunk = @chunks[@index]
71
71
  @index += 1
@@ -36,9 +36,14 @@ module Async
36
36
  @finished
37
37
  end
38
38
 
39
- def stop(error)
40
- @protocol.close
41
- @finished = true
39
+ def close(error = nil)
40
+ # We only close the connection if we haven't completed reading the entire body:
41
+ unless @finished
42
+ @protocol.close
43
+ @finished = true
44
+ end
45
+
46
+ super
42
47
  end
43
48
 
44
49
  def read
@@ -55,6 +55,12 @@ module Async
55
55
  @output_length = 0
56
56
  end
57
57
 
58
+ def close(error = nil)
59
+ @stream.close unless @stream.closed?
60
+
61
+ super
62
+ end
63
+
58
64
  def length
59
65
  # We don't know the length of the output until after it's been compressed.
60
66
  nil
@@ -71,13 +77,6 @@ module Async
71
77
  end
72
78
  end
73
79
 
74
- def stop(error)
75
- # There are two ways for the stream to be closed. Either #read returns nil or #stop is called.
76
- @stream.close unless @stream.closed?
77
-
78
- super
79
- end
80
-
81
80
  def inspect
82
81
  "#{super} | \#<#{self.class} #{(ratio*100).round(2)}%>"
83
82
  end
@@ -46,6 +46,13 @@ module Async
46
46
  end
47
47
  end
48
48
 
49
+ def close(error = nil)
50
+ @file.close
51
+ @remaining = 0
52
+
53
+ super
54
+ end
55
+
49
56
  attr :offset
50
57
  attr :length
51
58
 
@@ -57,11 +64,6 @@ module Async
57
64
  @file.seek(@offset)
58
65
  end
59
66
 
60
- def close
61
- @file.close
62
- @remaining = 0
63
- end
64
-
65
67
  def read
66
68
  if @remaining > 0
67
69
  amount = [@remaining, @block_size].min
@@ -70,8 +72,6 @@ module Async
70
72
  @remaining -= chunk.bytesize
71
73
 
72
74
  return chunk
73
- else
74
- @file.close
75
75
  end
76
76
  end
77
77
  end
@@ -37,10 +37,12 @@ module Async
37
37
  @remaining == 0
38
38
  end
39
39
 
40
- def stop(error)
40
+ def close(error = nil)
41
41
  if @remaining != 0
42
42
  @stream.close
43
43
  end
44
+
45
+ super
44
46
  end
45
47
 
46
48
  def read
@@ -75,9 +77,11 @@ module Async
75
77
  @stream.closed?
76
78
  end
77
79
 
78
- def stop(error)
80
+ def close(error = nil)
79
81
  # We can't really do anything in this case except close the connection.
80
82
  @stream.close
83
+
84
+ super
81
85
  end
82
86
 
83
87
  def read
@@ -25,9 +25,17 @@ module Async
25
25
  module Body
26
26
  # A generic base class for wrapping body instances. Typically you'd override `#read`.
27
27
  class Readable
28
- # Read all remaining chunks into a buffered body.
29
- def close
30
- Buffered.for(self)
28
+ # Read all remaining chunks into a buffered body and close the underlying input.
29
+ def finish
30
+ buffered = Buffered.for(self)
31
+
32
+ self.close
33
+
34
+ return buffered
35
+ end
36
+
37
+ # The consumer can call stop to signal that the stream output has terminated.
38
+ def close(error = nil)
31
39
  end
32
40
 
33
41
  # Will read return any data?
@@ -44,11 +52,7 @@ module Async
44
52
  nil
45
53
  end
46
54
 
47
- # The consumer can call stop to signal that the stream output has terminated.
48
- def stop(error)
49
- end
50
-
51
- # Enumerate all chunks until finished. If an error is thrown, #stop will be invoked.
55
+ # Enumerate all chunks until finished. Then invoke `#close`.
52
56
  def each
53
57
  return to_enum unless block_given?
54
58
 
@@ -56,10 +60,8 @@ module Async
56
60
  yield chunk
57
61
  # chunk.clear
58
62
  end
59
- rescue
60
- stop($!)
61
-
62
- raise
63
+ ensure
64
+ self.close($!)
63
65
  end
64
66
 
65
67
  # Read all remaining chunks into a single binary string.
@@ -34,24 +34,19 @@ module Async
34
34
  end
35
35
  end
36
36
 
37
- # Immediately stop reading the body. May close the underlying connection. Discards body.
38
- def stop(error = EOFError)
39
- if self.body
40
- self.body.stop(error)
41
- self.body = nil
42
- end
43
- end
44
-
45
37
  # Gracefully finish reading the body. This will buffer the remainder of the body.
46
38
  def finish
47
39
  if self.body
48
- self.body = self.body.close
40
+ self.body = self.body.finish
49
41
  end
50
42
  end
51
43
 
52
- # Close the connection as quickly as possible. Discards body.
53
- def close
54
- self.stop
44
+ # Close the connection as quickly as possible. Discards body. May close the underlying connection if necessary to terminate the stream.
45
+ def close(error = nil)
46
+ if self.body
47
+ self.body.close(error)
48
+ self.body = nil
49
+ end
55
50
  end
56
51
 
57
52
  # Whether there is a body?
@@ -23,7 +23,7 @@ require_relative 'wrapper'
23
23
  module Async
24
24
  module HTTP
25
25
  module Body
26
- # A body which buffers all it's contents.
26
+ # A body which buffers all it's contents as it is `#read`.
27
27
  class Rewindable < Wrapper
28
28
  def initialize(body)
29
29
  super(body)
@@ -44,7 +44,7 @@ module Async
44
44
  @remaining = remaining
45
45
  end
46
46
 
47
- def stop(*)
47
+ def close(*)
48
48
  super
49
49
 
50
50
  @callback.call
@@ -29,6 +29,20 @@ module Async
29
29
  @body = body
30
30
  end
31
31
 
32
+ # The wrapped body.
33
+ attr :body
34
+
35
+ # Buffer any remaining body.
36
+ def finish
37
+ @body.finish
38
+ end
39
+
40
+ def close(error = nil)
41
+ @body.close(error)
42
+
43
+ super
44
+ end
45
+
32
46
  def empty?
33
47
  @body.empty?
34
48
  end
@@ -37,22 +51,11 @@ module Async
37
51
  @body.length
38
52
  end
39
53
 
40
- # Buffer any remaining body.
41
- def close
42
- @body = @body.close
43
-
44
- return self
45
- end
46
-
47
54
  # Read the next available chunk.
48
55
  def read
49
56
  @body.read
50
57
  end
51
58
 
52
- def stop(error)
53
- @body.stop(error)
54
- end
55
-
56
59
  def inspect
57
60
  return @body.inspect
58
61
  end
@@ -27,13 +27,30 @@ module Async
27
27
  module Body
28
28
  # A dynamic body which you can write to and read from.
29
29
  class Writable < Readable
30
+ class Closed < StandardError
31
+ end
32
+
30
33
  def initialize
31
34
  @queue = Async::Queue.new
32
35
 
33
36
  @count = 0
34
37
 
35
38
  @finished = false
36
- @stopped = nil
39
+
40
+ @closed = false
41
+ @error = nil
42
+ end
43
+
44
+ # Stop generating output; cause the next call to write to fail with the given error.
45
+ def close(error = nil)
46
+ unless @closed
47
+ @queue.enqueue(nil)
48
+
49
+ @closed = true
50
+ @error = error
51
+ end
52
+
53
+ super
37
54
  end
38
55
 
39
56
  # Has the producer called #finish and has the reader consumed the nil token?
@@ -43,11 +60,6 @@ module Async
43
60
 
44
61
  # Read the next available chunk.
45
62
  def read
46
- # I'm not sure if this is a good idea.
47
- # if @stopped
48
- # raise @stopped
49
- # end
50
-
51
63
  return if @finished
52
64
 
53
65
  unless chunk = @queue.dequeue
@@ -57,17 +69,12 @@ module Async
57
69
  return chunk
58
70
  end
59
71
 
60
- # Stop generating output; cause the next call to write to fail with the given error.
61
- def stop(error)
62
- @stopped ||= error
63
- end
64
-
65
72
  # Write a single chunk to the body. Signal completion by calling `#finish`.
66
73
  def write(chunk)
67
74
  # If the reader breaks, the writer will break.
68
75
  # The inverse of this is less obvious (*)
69
- if @stopped
70
- raise @stopped
76
+ if @closed
77
+ raise(@error || Closed)
71
78
  end
72
79
 
73
80
  # TODO should this yield if the queue is full?
@@ -78,11 +85,6 @@ module Async
78
85
 
79
86
  alias << write
80
87
 
81
- # Signal that output has finished. This must be called at least once.
82
- def finish
83
- @queue.enqueue(nil)
84
- end
85
-
86
88
  def inspect
87
89
  "\#<#{self.class} #{@count} chunks written#{@finished ? ', finished' : ''}>"
88
90
  end
@@ -70,7 +70,7 @@ module Async
70
70
  end
71
71
 
72
72
  if end_stream
73
- @input.finish
73
+ @input.close
74
74
  end
75
75
  end
76
76
 
@@ -70,9 +70,9 @@ module Async
70
70
  end
71
71
 
72
72
  if end_stream
73
- @input.finish
73
+ @input.close
74
74
  end
75
- rescue EOFError
75
+ rescue
76
76
  @stream.send_reset_stream(0)
77
77
  end
78
78
 
@@ -56,7 +56,10 @@ module Async
56
56
  elsif chunk = @body.read
57
57
  # There was a new chunk of data to send
58
58
  else
59
- @body = nil
59
+ if @body
60
+ @body.close
61
+ @body = nil
62
+ end
60
63
 
61
64
  # @body.read above might take a while and a stream reset might be received in the mean time.
62
65
  unless closed?
@@ -109,7 +112,7 @@ module Async
109
112
  error_code = super
110
113
 
111
114
  if @body
112
- @body.stop(EOFError.new(error_code))
115
+ @body.close(EOFError.new(error_code))
113
116
  @body = nil
114
117
  end
115
118
 
@@ -75,7 +75,7 @@ module Async
75
75
  end
76
76
  end
77
77
 
78
- def stop(error)
78
+ def close(error = nil)
79
79
  complete_statistics(error)
80
80
 
81
81
  super
@@ -20,6 +20,6 @@
20
20
 
21
21
  module Async
22
22
  module HTTP
23
- VERSION = "0.31.1"
23
+ VERSION = "0.32.0"
24
24
  end
25
25
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-http
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.31.1
4
+ version: 0.32.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: 2018-09-30 00:00:00.000000000 Z
11
+ date: 2018-10-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async