codec.mojo (2491B)
1 from std.collections import Optional 2 3 from json import Value, dumps, loads 4 5 from hyf_stdio.envelope import ( 6 WireErrorResponse, 7 WireRequest, 8 WireSuccessResponse, 9 ) 10 11 12 @fieldwise_init 13 struct RequestCorrelation(Copyable, Movable): 14 var request_id: String 15 var trace_id: Optional[String] 16 17 18 def _extract_optional_string(value: Value, key: String) -> Optional[String]: 19 if not value.is_object(): 20 return None 21 22 for candidate in value.object_keys(): 23 if candidate == key: 24 try: 25 var field_value = value[key] 26 if field_value.is_string(): 27 return String(field_value.string_value()) 28 except e: 29 pass 30 return None 31 return None 32 33 34 def _root_key_occurrences(value: Value, key: String) -> Int: 35 if not value.is_object(): 36 return 0 37 var count = 0 38 for candidate in value.object_keys(): 39 if candidate == key: 40 count += 1 41 return count 42 43 44 def decode_request(line: String) raises -> WireRequest: 45 if line == "": 46 raise Error("request line must not be empty") 47 48 var json = loads(line) 49 return WireRequest.from_json(json) 50 51 52 def extract_request_correlation(line: String) -> RequestCorrelation: 53 var request_id = String() 54 var trace_id: Optional[String] = None 55 56 if line == "": 57 return RequestCorrelation(request_id=request_id, trace_id=trace_id^) 58 59 try: 60 var json = loads(line) 61 # ADR-0026 D46 CR04: only a single unambiguous correlation key is 62 # trusted. A duplicated request_id/trace_id is ambiguous, so recovery 63 # uses the existing no-trustworthy-correlation behavior instead of 64 # first/last-wins correlation. 65 var extracted_request_id = _extract_optional_string(json, "request_id") 66 if ( 67 extracted_request_id 68 and _root_key_occurrences(json, "request_id") == 1 69 ): 70 request_id = extracted_request_id.value() 71 72 var extracted_trace_id = _extract_optional_string(json, "trace_id") 73 if _root_key_occurrences(json, "trace_id") == 1: 74 trace_id = extracted_trace_id 75 except e: 76 pass 77 78 return RequestCorrelation(request_id=request_id, trace_id=trace_id^) 79 80 81 def encode_success(response: WireSuccessResponse) raises -> String: 82 return dumps(response.to_json_value()) 83 84 85 def encode_error(response: WireErrorResponse) raises -> String: 86 return dumps(response.to_json_value())