You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: lib/protocol/http/body/streamable.rb
+26-13
Original file line number
Diff line number
Diff line change
@@ -17,9 +17,14 @@ module Body
17
17
#
18
18
# When invoking `call(stream)`, the stream can be read from and written to, and closed. However, the stream is only guaranteed to be open for the duration of the `call(stream)` call. Once the method returns, the stream **should** be closed by the server.
19
19
moduleStreamable
20
+
# Raised when an operation is attempted on a closed stream.
20
21
classClosedError < StandardError
21
22
end
22
23
24
+
# Raised when a streaming body is consumed more than once.
25
+
classConsumedError < StandardError
26
+
end
27
+
23
28
defself.new(*arguments)
24
29
ifarguments.size == 1
25
30
DeferredBody.new(*arguments)
@@ -63,20 +68,36 @@ def write(chunk)
63
68
end
64
69
end
65
70
71
+
# Indicates that no further output will be generated.
72
+
defclose_write(error=nil)
73
+
# We might want to specialize the implementation later...
74
+
close(error)
75
+
end
76
+
66
77
# Can be invoked by the block to close the stream. Closing the output means that no more chunks will be generated.
67
78
defclose(error=nil)
68
79
iffrom=@from
69
80
# We are closing from within the output fiber, so we need to transfer back to `@from`:
70
81
@from=nil
71
-
from.transfer(nil)
82
+
iferror
83
+
from.raise(error)
84
+
else
85
+
from.transfer(nil)
86
+
end
72
87
elsif@fiber
73
88
# We are closing from outside the output fiber, so we need to resume the fiber appropriately:
74
89
@from=Fiber.current
75
90
76
91
iferror
92
+
# The fiber will be resumed from where it last called write, and we will raise the error there:
77
93
@fiber.raise(error)
78
94
else
79
-
@fiber.transfer(nil)
95
+
begin
96
+
# If we get here, it means we are closing the fiber from the outside, so we need to transfer control back to the fiber:
# If the fiber then tries to write to the stream, it will raise a ClosedError, and we will end up here. We can ignore it, as we are already closing the stream and don't care about further writes.
100
+
end
80
101
end
81
102
end
82
103
end
@@ -105,7 +126,7 @@ def stream?
105
126
defread
106
127
if@output.nil?
107
128
if@block.nil?
108
-
raise"Streaming body has already been consumed!"
129
+
raiseConsumedError,"Streaming body has already been consumed!"
109
130
end
110
131
111
132
@output=Output.new(@input,@block)
@@ -120,7 +141,7 @@ def read
120
141
# The block can read and write to the stream, and must close the stream when finishing.
121
142
defcall(stream)
122
143
if@block.nil?
123
-
raise"Streaming block has already been consumed!"
144
+
raiseConsumedError,"Streaming block has already been consumed!"
124
145
end
125
146
126
147
block=@block
@@ -153,25 +174,17 @@ def close(error = nil)
153
174
classDeferredBody < Body
154
175
definitialize(block)
155
176
super(block,Writable.new)
156
-
@finishing=false
157
-
end
158
-
159
-
defclose(error=nil)
160
-
returnunless@finishing
161
-
super
162
177
end
163
178
164
179
# Stream the response body into the block's input.
# Stop generating output; cause the next call to write to fail with the given error. Does not prevent existing chunks from being read. In other words, this indicates both that no more data will be or should be written to the body.
36
30
defclose(error=nil)
37
-
unless@closed
38
-
@queue.close
39
-
40
-
@closed=true
41
-
@error=error
42
-
end
31
+
@error ||= error
32
+
33
+
@queue.clear
34
+
@queue.close
43
35
44
36
super
45
37
end
46
38
47
39
defclosed?
48
-
@closed
40
+
@queue.closed?
49
41
end
50
42
51
43
defready?
@@ -59,23 +51,23 @@ def empty?
59
51
60
52
# Read the next available chunk.
61
53
defread
54
+
if@error
55
+
raise@error
56
+
end
57
+
62
58
@queue.pop
63
59
end
64
60
65
61
# Write a single chunk to the body. Signal completion by calling `#finish`.
66
62
defwrite(chunk)
67
-
# If the reader breaks, the writer will break.
68
-
if@closed
63
+
if@queue.closed?
69
64
raise(@error || Closed)
70
65
end
71
66
72
67
@queue.push(chunk)
73
68
@count += 1
74
69
end
75
70
76
-
# This alias is provided for compatibility with template generation.
0 commit comments