app.services.ingest¶
The shared ingest path used by poll and push intake.
One document goes through exactly these steps, whoever delivered it:
parse and validate (
app.domain.records.parse_record());compute the canonical digest (
app.domain.hashing.content_digest()) – any client-supplied digest is ignored;store the immutable snapshot (
put_revision) of the canonical text;render the Markdown body (and, for an erratum, its original, corrected and notes sections) with markdown-it-py and sanitize the HTML with nh3;
upsert the published row, or the candidate row (replace or create-only), with its per-record validation issues.
prepare_document() (steps 1, 2 and 4) is pure, so push intake can
inspect the result (e.g. compare the document UUID with the request)
before writing anything; ingest_document() adds steps 3 and 5.
Ingest never touches decision_event: approval history is keyed by
identity and digest and is never rewritten by intake. Callers run ingest
inside lock_registration().
Relationship issues (missing_target, ambiguous_target,
duplicate_uuid) are not stored by ingest. They depend on other
records – also those of other registrations, which can change without
this record changing – so they are computed at read time from
list_relationship_summaries() with
app.domain.relationships.RelationshipIndex (phase 05, catalog
service). Stored issues therefore hold only the per-document
findings of parse_record().
Public API: IncomingDocument, PreparedDocument,
IngestResult, render_markdown(),
render_erratum(), prepare_document(), ingest_document().
- class app.services.ingest.IncomingDocument(*, source_id, project, path, ref, content, change_token=None, source_url=None, author=None)¶
Bases:
objectOne delivered document, independent of the intake path.
- Parameters:
source_id (
str) – Owning registration id.project (
str) – Owning project path.path (
str) – File path inside the project.ref (
str) – Branch/ref the content came from.content (
bytes) – The exact bytes fetched or pushed.change_token (
str|None) – Source change token (Nonefor pushes).source_url (
str|None) – Link to the file at the source, if any.
- class app.services.ingest.PreparedDocument(*, parsed, digest, text, record)¶
Bases:
objectA parsed, hashed and rendered document, ready to be stored.
- Parameters:
parsed (
ParsedRecord) – Parse and validation result.digest (
str) – Canonical digest string.text (
str) – Canonical text stored as the revision snapshot.record (
RecordWrite) – The row to write.
- parsed: ParsedRecord¶
- record: RecordWrite¶
- class app.services.ingest.IngestResult(*, record_id, kind, digest, created, digest_changed, previous_digest, record_key, issues)¶
Bases:
objectOutcome of ingesting one document.
- Parameters:
record_id (
UUID) – Stored row id.kind (
RecordState) – Published or candidate.digest (
str) – Canonical digest string.created (
bool) –Trueif a new row was inserted.digest_changed (
bool) –Trueif an existing row got new content.previous_digest (
str|None) – Digest before this write, if any.record_key (
str) – Identity key of the row.issues (
tuple[Issue,...]) – Per-document validation issues.
- kind: RecordState¶
- app.services.ingest.render_markdown(body)¶
Render a Markdown body to sanitized HTML.
- app.services.ingest.render_erratum(content)¶
Render the sections of an erratum to sanitized HTML.
- Parameters:
content (
ErratumContent|None) – Parsed erratum content,Nonefor a decision.- Return type:
- Returns:
The content to store (missing optional sections stay
None), orNonefor a decision.
- app.services.ingest.prepare_document(document)¶
Parse, validate, hash and render a document (pure).
Never raises for content problems.
- Parameters:
document (
IncomingDocument) – The delivered document.- Return type:
- Returns:
The prepared document.
- app.services.ingest.ingest_document(store, prepared, kind, *, create_only=False)¶
Store the snapshot and upsert the row of a prepared document.
- Parameters:
store (
CatalogStore) – Store of the caller’s (locked) unit of work.prepared (
PreparedDocument) – Output ofprepare_document().kind (
RecordState) – Published (poll) or candidate (push).create_only (
bool) – Candidates only: refuse to replace an existing candidate (POSTsemantics).
- Return type:
- Returns:
The outcome.
- Raises:
app.errors.CandidateExistsError – If create_only and the candidate exists.