Skip to content

Commit c3b502a

Browse files
Pigbibicodex
andcommitted
Separate feed status evidence from producer result
Co-Authored-By: Codex <noreply@openai.com>
1 parent 294e30b commit c3b502a

4 files changed

Lines changed: 633 additions & 86 deletions

File tree

Lines changed: 312 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,312 @@
1+
from __future__ import annotations
2+
3+
import hashlib
4+
import json
5+
import re
6+
from collections.abc import Iterable, Mapping
7+
from dataclasses import dataclass
8+
9+
10+
STATUS_VERSION = "pert.feed_primitives.v1"
11+
MAX_SAFE_JSON_INTEGER = 2**53 - 1
12+
MAX_ROWS_PER_FEED = 10_000
13+
_DIGEST_RE = re.compile(r"^[0-9a-f]{64}$")
14+
_ERROR_RE = re.compile(r"^[a-z][a-z0-9_]{0,63}$")
15+
_ROW_KEYS = ("item_id", "published_at", "source_type", "source_url", "author", "text")
16+
_RECORD_KEYS = frozenset({"feed_id", "feed_url", "kind", "state", "rows", "error_code"})
17+
_WIRE_KEYS = frozenset(
18+
{
19+
"status_version",
20+
"configured_feed_count",
21+
"feed_count",
22+
"successful_feed_count",
23+
"failed_feed_count",
24+
"quarantined_feed_count",
25+
"accepted_row_count",
26+
"rejected_row_count",
27+
"publication_complete",
28+
"eligible_for_live_publication",
29+
"aggregate_row_digest",
30+
"feeds",
31+
}
32+
)
33+
_FEED_WIRE_KEYS = frozenset(
34+
{
35+
"feed_id",
36+
"feed_url",
37+
"kind",
38+
"state",
39+
"accepted_row_count",
40+
"rejected_row_count",
41+
"row_digest",
42+
"error_code",
43+
}
44+
)
45+
46+
47+
class PrimitiveStatusError(ValueError):
48+
"""Sanitized status-contract error."""
49+
50+
def __init__(self, code: str):
51+
super().__init__(code)
52+
self.code = code
53+
54+
55+
def _fail(code: str) -> None:
56+
raise PrimitiveStatusError(code)
57+
58+
59+
def _mapping(value: object, keys: frozenset[str], code: str) -> dict[str, object]:
60+
if not isinstance(value, Mapping):
61+
_fail(code)
62+
try:
63+
result = dict(value)
64+
except (AttributeError, KeyError, OverflowError, RuntimeError, TypeError, UnicodeError, ValueError):
65+
_fail(code)
66+
if set(result) != keys or any(type(key) is not str for key in result):
67+
_fail(code)
68+
return result
69+
70+
71+
def _string(value: object, code: str, *, allow_empty: bool = False) -> str:
72+
if type(value) is not str or (not allow_empty and not value) or any(ord(char) < 0x20 for char in value):
73+
_fail(code)
74+
return value
75+
76+
77+
def _integer(value: object, code: str) -> int:
78+
if type(value) is not int or value < 0 or value > MAX_SAFE_JSON_INTEGER:
79+
_fail(code)
80+
return value
81+
82+
83+
@dataclass(frozen=True)
84+
class PrimitiveRow:
85+
item_id: str
86+
published_at: str
87+
source_type: str
88+
source_url: str
89+
author: str
90+
text: str
91+
92+
@classmethod
93+
def from_mapping(cls, value: object) -> PrimitiveRow:
94+
data = _mapping(value, frozenset(_ROW_KEYS), "row_invalid")
95+
values = [_string(data[key], "row_invalid", allow_empty=key == "author") for key in _ROW_KEYS]
96+
return cls(*values)
97+
98+
def to_mapping(self) -> dict[str, str]:
99+
return {key: getattr(self, key) for key in _ROW_KEYS}
100+
101+
102+
@dataclass(frozen=True)
103+
class FetchResult:
104+
rows: tuple[PrimitiveRow, ...]
105+
status: dict[str, object]
106+
publication_eligible: bool
107+
hard_failure: bool
108+
109+
110+
def _row_key(row: PrimitiveRow) -> tuple[str, str]:
111+
return row.published_at, row.item_id
112+
113+
114+
def _canonical(value: object, code: str) -> bytes:
115+
try:
116+
return json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":"), allow_nan=False).encode(
117+
"utf-8"
118+
)
119+
except (RecursionError, TypeError, UnicodeError, ValueError):
120+
_fail(code)
121+
122+
123+
def _rows_digest(rows: list[PrimitiveRow]) -> str:
124+
ordered = sorted(rows, key=_row_key)
125+
return hashlib.sha256(_canonical([row.to_mapping() for row in ordered], "row_digest_invalid")).hexdigest()
126+
127+
128+
def _record(value: object) -> tuple[dict[str, object], list[PrimitiveRow]]:
129+
data = _mapping(value, _RECORD_KEYS, "feed_invalid")
130+
feed_id = _string(data["feed_id"], "feed_invalid")
131+
feed_url = _string(data["feed_url"], "feed_invalid")
132+
kind = data["kind"]
133+
state = data["state"]
134+
if type(kind) is not str or kind not in {"rss2", "atom", "unknown"}:
135+
_fail("feed_kind_invalid")
136+
if type(state) is not str or state not in {"accepted", "failed", "quarantined"}:
137+
_fail("feed_state_invalid")
138+
rows_value = data["rows"]
139+
if not isinstance(rows_value, (list, tuple)) or len(rows_value) > MAX_ROWS_PER_FEED:
140+
_fail("feed_rows_invalid")
141+
rows = [PrimitiveRow.from_mapping(row) for row in rows_value]
142+
error = data["error_code"]
143+
if error is not None and (type(error) is not str or not _ERROR_RE.fullmatch(error)):
144+
_fail("feed_error_invalid")
145+
if state == "accepted" and (kind not in {"rss2", "atom"} or not rows or error is not None):
146+
_fail("feed_state_invalid")
147+
if state == "quarantined" and (kind not in {"rss2", "atom"} or rows or error is None):
148+
_fail("feed_state_invalid")
149+
if state == "failed" and (rows or error is None):
150+
_fail("feed_state_invalid")
151+
return {"feed_id": feed_id, "feed_url": feed_url, "kind": kind, "state": state, "error_code": error}, rows
152+
153+
154+
def _wire_feed(data: dict[str, object], rows: list[PrimitiveRow]) -> dict[str, object]:
155+
accepted = data["state"] == "accepted"
156+
return {
157+
"feed_id": data["feed_id"],
158+
"feed_url": data["feed_url"],
159+
"kind": data["kind"],
160+
"state": data["state"],
161+
"accepted_row_count": len(rows) if accepted else 0,
162+
"rejected_row_count": 0,
163+
"row_digest": _rows_digest(rows) if accepted else hashlib.sha256(b"[]").hexdigest(),
164+
"error_code": data["error_code"],
165+
}
166+
167+
168+
def build_status(feed_records: Iterable[Mapping[str, object]]) -> dict[str, object]:
169+
try:
170+
records = list(feed_records)
171+
except (AttributeError, RuntimeError, TypeError, ValueError):
172+
_fail("status_invalid")
173+
parsed = [_record(record) for record in records]
174+
if not parsed:
175+
_fail("feed_config_empty")
176+
if len({data["feed_id"] for data, _ in parsed}) != len(parsed):
177+
_fail("feed_duplicate")
178+
parsed.sort(key=lambda item: (item[0]["feed_id"], item[0]["feed_url"]))
179+
feeds = [_wire_feed(data, rows) for data, rows in parsed]
180+
accepted_rows = sorted(
181+
[row for data, rows in parsed if data["state"] == "accepted" for row in rows], key=_row_key
182+
)
183+
failed = sum(data["state"] == "failed" for data, _ in parsed)
184+
quarantined = sum(data["state"] == "quarantined" for data, _ in parsed)
185+
complete = failed == 0 and quarantined == 0
186+
return {
187+
"status_version": STATUS_VERSION,
188+
"configured_feed_count": len(parsed),
189+
"feed_count": len(parsed),
190+
"successful_feed_count": len(parsed) - failed - quarantined,
191+
"failed_feed_count": failed,
192+
"quarantined_feed_count": quarantined,
193+
"accepted_row_count": len(accepted_rows),
194+
"rejected_row_count": 0,
195+
"publication_complete": complete,
196+
"eligible_for_live_publication": complete,
197+
"aggregate_row_digest": _rows_digest(accepted_rows),
198+
"feeds": feeds,
199+
}
200+
201+
202+
def build_fetch_result(feed_records: Iterable[Mapping[str, object]]) -> FetchResult:
203+
try:
204+
records = list(feed_records)
205+
except (AttributeError, RuntimeError, TypeError, ValueError):
206+
_fail("status_invalid")
207+
status = build_status(records)
208+
parsed = [_record(record) for record in records]
209+
rows = sorted(
210+
[row for data, feed_rows in parsed if data["state"] == "accepted" for row in feed_rows], key=_row_key
211+
)
212+
failed = status["failed_feed_count"] > 0
213+
return FetchResult(tuple(rows), status, bool(status["eligible_for_live_publication"]), failed)
214+
215+
216+
def _validate_wire(value: object) -> dict[str, object]:
217+
data = _mapping(value, _WIRE_KEYS, "status_invalid")
218+
if data["status_version"] != STATUS_VERSION:
219+
_fail("status_version_invalid")
220+
counter_keys = _WIRE_KEYS - {
221+
"status_version",
222+
"publication_complete",
223+
"eligible_for_live_publication",
224+
"aggregate_row_digest",
225+
"feeds",
226+
}
227+
for key in counter_keys:
228+
_integer(data[key], "status_counter_invalid")
229+
for key in ("publication_complete", "eligible_for_live_publication"):
230+
if type(data[key]) is not bool:
231+
_fail("status_flag_invalid")
232+
aggregate = _string(data["aggregate_row_digest"], "status_digest_invalid")
233+
if not _DIGEST_RE.fullmatch(aggregate):
234+
_fail("status_digest_invalid")
235+
feeds = data["feeds"]
236+
if not isinstance(feeds, list):
237+
_fail("feed_invalid")
238+
previous: tuple[str, str] | None = None
239+
feed_ids: set[str] = set()
240+
for value in feeds:
241+
item = _mapping(value, _FEED_WIRE_KEYS, "feed_invalid")
242+
feed_id = _string(item["feed_id"], "feed_invalid")
243+
feed_url = _string(item["feed_url"], "feed_invalid")
244+
key = (feed_id, feed_url)
245+
if feed_id in feed_ids:
246+
_fail("feed_duplicate")
247+
if previous is not None and key <= previous:
248+
_fail("feed_order_invalid")
249+
previous = key
250+
feed_ids.add(feed_id)
251+
kind = item["kind"]
252+
state = item["state"]
253+
if type(kind) is not str or kind not in {"rss2", "atom", "unknown"}:
254+
_fail("feed_kind_invalid")
255+
if type(state) is not str or state not in {"accepted", "failed", "quarantined"}:
256+
_fail("feed_state_invalid")
257+
if state in {"accepted", "quarantined"} and kind not in {"rss2", "atom"}:
258+
_fail("feed_kind_invalid")
259+
accepted_count = _integer(item["accepted_row_count"], "feed_counter_invalid")
260+
_integer(item["rejected_row_count"], "feed_counter_invalid")
261+
if state == "accepted" and accepted_count == 0:
262+
_fail("feed_state_invalid")
263+
if state != "accepted" and accepted_count != 0:
264+
_fail("feed_state_invalid")
265+
digest = _string(item["row_digest"], "status_digest_invalid")
266+
if not _DIGEST_RE.fullmatch(digest):
267+
_fail("status_digest_invalid")
268+
error = item["error_code"]
269+
if state == "accepted" and error is not None:
270+
_fail("feed_state_invalid")
271+
if state != "accepted" and (type(error) is not str or not _ERROR_RE.fullmatch(error)):
272+
_fail("feed_error_invalid")
273+
if data["configured_feed_count"] != len(feeds) or data["feed_count"] != len(feeds):
274+
_fail("status_counter_invalid")
275+
accepted = sum(item["state"] == "accepted" for item in feeds)
276+
failed = sum(item["state"] == "failed" for item in feeds)
277+
quarantined = sum(item["state"] == "quarantined" for item in feeds)
278+
accepted_rows = sum(item["accepted_row_count"] for item in feeds)
279+
if data["successful_feed_count"] != accepted or data["failed_feed_count"] != failed:
280+
_fail("status_counter_invalid")
281+
if data["quarantined_feed_count"] != quarantined or data["accepted_row_count"] != accepted_rows:
282+
_fail("status_counter_invalid")
283+
complete = failed == 0 and quarantined == 0
284+
if data["publication_complete"] != complete or data["eligible_for_live_publication"] != complete:
285+
_fail("status_flag_invalid")
286+
return data
287+
288+
289+
def serialize_status(status: Mapping[str, object]) -> bytes:
290+
return _canonical(_validate_wire(status), "status_invalid")
291+
292+
293+
def parse_status_bytes(payload: bytes) -> dict[str, object]:
294+
if type(payload) is not bytes:
295+
_fail("status_bytes_invalid")
296+
try:
297+
value = json.loads(payload.decode("utf-8"), object_pairs_hook=_reject_duplicate_keys)
298+
except (UnicodeError, json.JSONDecodeError, RecursionError):
299+
_fail("status_bytes_invalid")
300+
data = _validate_wire(value)
301+
if serialize_status(data) != payload:
302+
_fail("status_noncanonical")
303+
return data
304+
305+
306+
def _reject_duplicate_keys(pairs: list[tuple[str, object]]) -> dict[str, object]:
307+
result: dict[str, object] = {}
308+
for key, value in pairs:
309+
if key in result:
310+
_fail("status_duplicate_key")
311+
result[key] = value
312+
return result

0 commit comments

Comments
 (0)