Repository navigation
Expand file tree
/
Copy pathtest_headers.py
More file actions
130 lines (100 loc) · 4.89 KB
/
Copy pathtest_headers.py
File metadata and controls
130 lines (100 loc) · 4.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
"""Tests for the core out-of-band transport-header seam (ADR-0028).
The dependency-free core: ``BabelQueue.publish_with_headers`` (produce side) and
``headers_from_context`` (consume side, surfaced by the runtime), plus the ``merge_headers``
helper. No broker and no OpenTelemetry needed.
"""
from __future__ import annotations
from babelqueue import BabelQueue, EnvelopeCodec, headers_from_context
from babelqueue.headers import _headers_scope, merge_headers
from babelqueue.transport import InMemoryTransport, ReceivedMessage, Transport
def test_headers_from_context_default_empty():
assert headers_from_context() == {}
def test_headers_scope_surfaces_and_resets():
with _headers_scope({"traceparent": "00-abc"}):
assert headers_from_context().get("traceparent") == "00-abc"
assert headers_from_context() == {} # scope reset the contextvar
def test_headers_scope_none_is_nil_safe():
with _headers_scope(None):
assert headers_from_context() == {}
def test_merge_headers_drops_blanks_and_later_wins():
merged = merge_headers(
None, # a falsy source is skipped
{"traceparent": "00-1", "drop-empty": "", "": "no-key"},
{}, # empty source is skipped
{"traceparent": "00-2", "tracestate": "x=1"},
)
assert merged == {"traceparent": "00-2", "tracestate": "x=1"} # later source wins, blanks gone
def test_publish_with_headers_carries_over_inmemory():
t = InMemoryTransport()
app = BabelQueue(transport=t, queue="orders")
msg_id = app.publish_with_headers(
"urn:babel:orders:created", {"order_id": 1}, {"traceparent": "00-abc"}
)
msg = t.pop("orders", 0)
assert msg is not None
assert msg.headers.get("traceparent") == "00-abc"
# the body is the plain encoded envelope — the header rode out of band, not in the envelope
env = EnvelopeCodec.decode(msg.body)
assert env["meta"]["id"] == msg_id
assert "traceparent" not in env and "traceparent" not in env.get("meta", {})
def test_publish_with_empty_headers_is_byte_identical_to_publish():
t = InMemoryTransport()
app = BabelQueue(transport=t, queue="orders")
app.publish_with_headers("urn:babel:orders:created", {"order_id": 1}, {}, trace_id="t-1")
framed = t.pop("orders", 0)
app.publish("urn:babel:orders:created", {"order_id": 1}, trace_id="t-1")
plain = t.pop("orders", 0)
assert framed is not None and plain is not None
assert framed.headers == {} and plain.headers == {}
# same trace_id + same data → identical envelope bodies bar the random meta.id
fa, pa = EnvelopeCodec.decode(framed.body), EnvelopeCodec.decode(plain.body)
fa["meta"].pop("id"), pa["meta"].pop("id")
fa["meta"].pop("created_at"), pa["meta"].pop("created_at")
assert fa == pa
def test_runtime_surfaces_delivered_headers_to_handler():
t = InMemoryTransport()
app = BabelQueue(transport=t, queue="orders")
seen = {}
@app.handler("urn:babel:orders:created")
def _on(data, meta):
seen["headers"] = dict(headers_from_context())
app.publish_with_headers(
"urn:babel:orders:created", {"order_id": 1}, {"traceparent": "00-deadbeef"}
)
app.consume("orders", max_messages=1, timeout=0)
assert seen["headers"].get("traceparent") == "00-deadbeef"
# the scope is reset once dispatch returns
assert headers_from_context() == {}
class _PlainTransport(Transport):
"""A Transport that is deliberately NOT a HeaderPublisher (no publish_with_headers)."""
def __init__(self):
self._inner = InMemoryTransport()
def publish(self, queue, body):
self._inner.publish(queue, body)
def pop(self, queue, timeout=1.0):
return self._inner.pop(queue, timeout)
def ack(self, message):
self._inner.ack(message)
def test_publish_with_headers_falls_back_when_transport_cannot_carry():
t = _PlainTransport()
app = BabelQueue(transport=t, queue="orders")
# No error, headers simply dropped (degrades to plain publish), exactly like Redrive.
app.publish_with_headers("urn:babel:orders:created", {"order_id": 1}, {"traceparent": "00-x"})
msg = t.pop("orders", 0)
assert msg is not None and msg.headers == {}
assert isinstance(msg, ReceivedMessage)
def test_out_of_band_headers_drops_projection_keys_and_decodes_bytes():
from babelqueue.headers import out_of_band_headers
raw = [
("bq-job", b"urn:babel:orders:created"),
("bq-delay", b"5000"),
(b"traceparent", b"00-abc"),
("bq-replay-bypass", "1"),
("traceparent", b"00-second"), # a repeated key: the first one wins
("blank", b""),
("none", None),
]
assert out_of_band_headers(raw) == {"traceparent": "00-abc", "bq-replay-bypass": "1"}
assert out_of_band_headers({"bq_attempts": "1", "tracestate": "a=1"}) == {"tracestate": "a=1"}
assert out_of_band_headers(None) == {} and out_of_band_headers([]) == {}
assert out_of_band_headers(42) == {}