Class: HotCell::Response
- Inherits:
-
Object
- Object
- HotCell::Response
- Extended by:
- Fields
- Defined in:
- lib/hot_cell/response.rb
Overview
One line of JSON. Outputs are posted and flushed before success is reported, so the cold side may
read as soon as it sees ok.
timing is present on every response, success or failure, and it is also the cell's tracing
channel. A cell cannot reach a trace collector, so anything it knows about its own internals
travels back here or not at all. An operation may add its own keys, and a client should treat the
map as open.
Instance Attribute Summary collapse
-
#failure ⇒ Object
readonly
Returns the value of attribute failure.
-
#result ⇒ Object
readonly
Returns the value of attribute result.
-
#timing ⇒ Object
readonly
Returns the value of attribute timing.
-
#version ⇒ Object
readonly
Returns the value of attribute version.
Class Method Summary collapse
- .failed(failure, timing: {}) ⇒ Object
- .noun ⇒ Object
- .ok(result: {}, timing: {}) ⇒ Object
-
.parse(line) ⇒ Object
okhas to be the boolean it says it is rather than anything truthy.
Instance Method Summary collapse
-
#initialize(result: nil, failure: nil, timing: {}, version: PROTOCOL_VERSION) ⇒ Response
constructor
A new instance of Response.
- #ok? ⇒ Boolean
- #to_line ⇒ Object
Constructor Details
#initialize(result: nil, failure: nil, timing: {}, version: PROTOCOL_VERSION) ⇒ Response
Returns a new instance of Response.
58 59 60 61 62 63 |
# File 'lib/hot_cell/response.rb', line 58 def initialize(result: nil, failure: nil, timing: {}, version: PROTOCOL_VERSION) @result = result @failure = failure @timing = timing @version = version end |
Instance Attribute Details
#failure ⇒ Object (readonly)
Returns the value of attribute failure.
12 13 14 |
# File 'lib/hot_cell/response.rb', line 12 def failure @failure end |
#result ⇒ Object (readonly)
Returns the value of attribute result.
12 13 14 |
# File 'lib/hot_cell/response.rb', line 12 def result @result end |
#timing ⇒ Object (readonly)
Returns the value of attribute timing.
12 13 14 |
# File 'lib/hot_cell/response.rb', line 12 def timing @timing end |
#version ⇒ Object (readonly)
Returns the value of attribute version.
12 13 14 |
# File 'lib/hot_cell/response.rb', line 12 def version @version end |
Class Method Details
.failed(failure, timing: {}) ⇒ Object
25 26 27 |
# File 'lib/hot_cell/response.rb', line 25 def failed(failure, timing: {}) new failure: failure, timing: timing end |
.noun ⇒ Object
17 18 19 |
# File 'lib/hot_cell/response.rb', line 17 def noun "response" end |
.ok(result: {}, timing: {}) ⇒ Object
21 22 23 |
# File 'lib/hot_cell/response.rb', line 21 def ok(result: {}, timing: {}) new result: result, timing: timing end |
.parse(line) ⇒ Object
ok has to be the boolean it says it is rather than anything truthy. This is the field the whole
taxonomy turns on, and Ruby's truthiness would read "false", 0 and [] as success — so a
malformed or hostile response could turn a failure into an ok carrying no result at all.
Accepted risk. Nothing inside result is checked, and a compromised cell chooses all of it.
Payload.validate! is not run on the way in, so a value JSON can carry but Ruby cannot serialize
again reaches the caller — 1e400 parses to Float::INFINITY, and an application that writes a
result to a JSON column raises there rather than here. The premise is that a result is data the
caller acts on and only the caller knows its shape, so the framework has no rule to apply and a
client with a specific expectation states it itself. ok is the exception because the taxonomy
turns on it and every caller depends on it equally.
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/hot_cell/response.rb', line 40 def parse(line) (line) do |parsed| ok = parsed[:ok] unless ok == true || ok == false raise MessageError, "response ok is #{ok.inspect} and must be true or false" end timing = parsed[:timing].is_a?(Hash) ? parsed[:timing] : {} if ok new version: parsed[:v], result: object(parsed, :result), timing: timing else new version: parsed[:v], failure: Failure.from_wire(object(parsed, :error)), timing: timing end end end |
Instance Method Details
#ok? ⇒ Boolean
65 66 67 |
# File 'lib/hot_cell/response.rb', line 65 def ok? failure.nil? end |
#to_line ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/hot_cell/response.rb', line 69 def to_line body = { v: version, ok: ok? } if ok? body[:result] = Payload.validate!(result, "result") else body[:error] = failure.to_h end body[:timing] = Payload.validate!(timing, "timing") line = JSON.generate(body) << "\n" if line.bytesize > MAX_RESPONSE_BYTES raise MessageError, "response is #{line.bytesize} bytes, over the #{MAX_RESPONSE_BYTES} byte limit" end line end |