Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions crates/ourios-ingester/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
//! durably (WAL-before-ack), lands Parquet in object storage, and runs
//! background maintenance. It spans three RFCs at different maturities:
//!
//! - **OTLP receiver** (RFC 0003, `drafted`) — the gRPC/HTTP ingest
//! front door + mining pipeline. [`receiver`] is a placeholder until
//! RFC 0003 reaches `red`; no ingest is implemented here yet.
//! - **OTLP receiver** (RFC 0003, `specified` → `red`) — the gRPC/HTTP
//! ingest front door + mining pipeline. The §5 acceptance criteria
//! (RFC0003.1–.15) are now enumerated as `#[ignore]`'d tests under
//! `tests/rfc0003_*`; [`receiver`] stays a placeholder until the
//! green slices land the ingest pipeline + WAL-before-ack path.
//! - **WAL-before-ack** (RFC 0008 / `CLAUDE.md` §3.4) — durability
//! before acknowledgement, via the shipped `ourios-wal`. Wired into
//! the ingest path once the receiver lands; not exercised here.
Expand Down
14 changes: 8 additions & 6 deletions crates/ourios-ingester/src/receiver.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
//! OTLP receiver — **placeholder** (RFC 0003, `drafted`).
//! OTLP receiver — **placeholder** (RFC 0003, `specified` → `red`).
//!
//! The ingest front door (OTLP logs over gRPC/HTTP), the Drain-derived
//! mining pipeline, and the WAL-before-ack durability path
//! (`CLAUDE.md` §3.4, RFC 0008) live here once RFC 0003 reaches `red`.
//! Nothing is implemented yet: this scaffold lands the crate and the
//! background compaction runner ([`crate::compactor`]) only, so the
//! receiver is deliberately empty rather than a half-built ingest path
//! ahead of its RFC.
//! (`CLAUDE.md` §3.4, RFC 0008) live here. The RFC is now `specified`,
//! and its §5 acceptance criteria (RFC0003.1–.15) are enumerated as
//! `#[ignore]`'d tests under `crates/ourios-ingester/tests/rfc0003_*` —
//! the `red` gate. This module stays deliberately empty until the green
//! slices land the ingest pipeline (wire decode → tenant fan-out →
//! WAL-before-ack → miner), rather than a half-built path ahead of
//! review.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//! RFC0003.10 — `dropped_attributes_count` preserved verbatim.
//!
//! Red gate (`specified → red`): `#[ignore]`'d until the receiver
//! lands.

/// Scenario RFC0003.10 — `dropped_attributes_count` preserved verbatim.
/// See `docs/rfcs/0003-otlp-receiver.md` §5.
#[ignore = "RFC 0003 red gate — implementation pending (RFC0003.10)"]
#[test]
fn rfc0003_10_dropped_attributes_count_is_reflected_not_recomputed() {
unimplemented!(
"RFC0003.10 — a wire dropped_attributes_count of 42 yields \
OtlpLogRecord.dropped_attributes_count == 42 exactly; the receiver \
reflects the wire claim and never recomputes it."
);
}
18 changes: 18 additions & 0 deletions crates/ourios-ingester/tests/rfc0003_11_transport_errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//! RFC0003.11 — Transport-level errors are controlled, not panics.
//!
//! Red gate (`specified → red`): `#[ignore]`'d until the receiver
//! lands.

/// Scenario RFC0003.11 — Transport-level errors are controlled, not panics.
/// See `docs/rfcs/0003-otlp-receiver.md` §5.
#[ignore = "RFC 0003 red gate — implementation pending (RFC0003.11)"]
#[test]
fn rfc0003_11_transport_errors_are_controlled() {
unimplemented!(
"RFC0003.11 — malformed protobuf, oversize body, unrecognised \
Content-Type, wrong path, and mid-decode gRPC cancellation each yield a \
controlled transport error (gRPC INVALID_ARGUMENT / RESOURCE_EXHAUSTED / \
CANCELLED; HTTP 400 / 413 / 415 / 404). No panic, process stays alive, \
and no OtlpBatch frame is appended."
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//! RFC0003.12 — Empty `ExportLogsServiceRequest` returns success without WAL write.
//!
//! Red gate (`specified → red`): `#[ignore]`'d until the receiver
//! lands.

/// Scenario RFC0003.12 — Empty `ExportLogsServiceRequest` returns success without WAL write.
/// See `docs/rfcs/0003-otlp-receiver.md` §5.
#[ignore = "RFC 0003 red gate — implementation pending (RFC0003.12)"]
#[test]
fn rfc0003_12_empty_request_succeeds_without_persisting() {
unimplemented!(
"RFC0003.12 — a zero-LogRecord request (empty resource_logs; empty \
scope_logs; empty log_records — all three shapes) returns success with \
partial_success unset (OTLP 'empty is success'), and invokes neither \
Wal::append/sync nor MinerCluster::ingest (asserted via a counting Wal \
wrapper)."
);
}
17 changes: 17 additions & 0 deletions crates/ourios-ingester/tests/rfc0003_13_compression.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//! RFC0003.13 — Compression over HTTP: identity and gzip MUST be supported.
//!
//! Red gate (`specified → red`): `#[ignore]`'d until the receiver
//! lands.

/// Scenario RFC0003.13 — Compression over HTTP: identity and gzip MUST be supported.
/// See `docs/rfcs/0003-otlp-receiver.md` §5.
#[ignore = "RFC 0003 red gate — implementation pending (RFC0003.13)"]
#[test]
fn rfc0003_13_identity_and_gzip_decode_equally_unsupported_is_415() {
unimplemented!(
"RFC0003.13 — the same payload sent with Content-Encoding: identity (or \
absent) and with Content-Encoding: gzip yields equal OtlpLogRecord \
sequences (both encodings are an OTLP MUST). An unsupported encoding \
(zstd, br) is rejected with HTTP 415; zstd is deferred per §9."
);
}
17 changes: 17 additions & 0 deletions crates/ourios-ingester/tests/rfc0003_14_path_config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//! RFC0003.14 — Default `/v1/logs` path with configurable override.
//!
//! Red gate (`specified → red`): `#[ignore]`'d until the receiver
//! lands.

/// Scenario RFC0003.14 — Default `/v1/logs` path with configurable override.
/// See `docs/rfcs/0003-otlp-receiver.md` §5.
#[ignore = "RFC 0003 red gate — implementation pending (RFC0003.14)"]
#[test]
fn rfc0003_14_default_path_and_configurable_override() {
unimplemented!(
"RFC0003.14 — a POST to the default /v1/logs is handled via the §6.2 HTTP \
path; a POST to any other path returns HTTP 404; and an operator-\
configured override path (e.g. /otlp/v1/logs) replaces /v1/logs as the \
accepted path without changing any other receiver behaviour."
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//! RFC0003.15 — Concurrent `Export` calls each obey WAL-before-ack independently `[§3.4]`.
//!
//! Red gate (`specified → red`): `#[ignore]`'d until the receiver
//! lands.

/// Scenario RFC0003.15 — Concurrent `Export` calls each obey WAL-before-ack independently.
/// See `docs/rfcs/0003-otlp-receiver.md` §5.
#[ignore = "RFC 0003 red gate — implementation pending (RFC0003.15)"]
#[test]
fn rfc0003_15_concurrent_exports_each_ack_after_their_own_sync() {
unimplemented!(
"RFC0003.15 — N >= 2 concurrent gRPC Export calls from independent \
connections each emit their ack only after their OWN batch's Wal::sync \
returns Ok and their own batch's records are durable. A per-call ordering \
probe checks the invariant independently per in-flight call."
);
}
19 changes: 19 additions & 0 deletions crates/ourios-ingester/tests/rfc0003_1_wal_before_ack.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//! RFC0003.1 — WAL-before-ack `[§3.4]`.
//!
//! Red gate (`specified → red`): this acceptance test enumerates
//! the §5 contract and is `#[ignore]`'d until the OTLP receiver
//! lands. The implementing PR removes the `#[ignore]` and the
//! `unimplemented!()` body together.

/// Scenario RFC0003.1 — WAL-before-ack.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — fixed in 3916155 across all 15 stubs (this same comment landed on each file). The /// See docs/rfcs/0003-otlp-receiver.md §5. line now sits in the per-test doc comment directly under /// Scenario RFC0003.<m> — <title>., matching the docs/verification.md §2.3/§6.3 canonical pattern; the redundant module-level //! See line was dropped.

/// See `docs/rfcs/0003-otlp-receiver.md` §5.
#[ignore = "RFC 0003 red gate — implementation pending (RFC0003.1)"]
#[test]
fn rfc0003_1_no_ack_before_every_record_is_durable() {
unimplemented!(
"RFC0003.1 — a request receives a 2xx / gRPC OK only after every record \
in the batch is durably WAL-written (Wal::sync returns Ok). An ordering \
probe set after sync returns is asserted true by the response writer and \
false by every pre-sync stage (mirrors the RFC0008.1 probe)."
);
}
19 changes: 19 additions & 0 deletions crates/ourios-ingester/tests/rfc0003_2_crash_before_ack.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//! RFC0003.2 — Crash-before-ack: at-least-once with retry tolerance `[§3.4]`.
//!
//! Red gate (`specified → red`): `#[ignore]`'d until the receiver
//! lands. Per §8 this uses a child-process harness mirroring
//! `wal_crash_fixture` (PR #126).

/// Scenario RFC0003.2 — Crash-before-ack: at-least-once with retry tolerance.
/// See `docs/rfcs/0003-otlp-receiver.md` §5.
#[ignore = "RFC 0003 red gate — implementation pending (RFC0003.2)"]
#[test]
fn rfc0003_2_crash_before_ack_is_at_least_once_not_lossy() {
unimplemented!(
"RFC0003.2 — SIGKILL the receiver between Wal::sync return and ack-emit, \
restart, re-issue the export; the post-restart WAL holds TWO OtlpBatch \
frames each round-tripping (prost) to a request equivalent to the input. \
Asserts no loss + safe retry; explicitly does NOT assert dedup \
(at-least-once per the OTLP duplicate-data section)."
);
}
17 changes: 17 additions & 0 deletions crates/ourios-ingester/tests/rfc0003_3_tenant_fanout.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//! RFC0003.3 — Tenant fan-out `[§3.7]`.
//!
//! Red gate (`specified → red`): `#[ignore]`'d until the receiver
//! lands.

/// Scenario RFC0003.3 — Tenant fan-out.
/// See `docs/rfcs/0003-otlp-receiver.md` §5.
#[ignore = "RFC 0003 red gate — implementation pending (RFC0003.3)"]
#[test]
fn rfc0003_3_two_resources_fan_out_without_cross_contamination() {
unimplemented!(
"RFC0003.3 — a single export with two ResourceLogs from different sources \
produces two distinct per-tenant streams; no record from Resource A \
appears in tenant B's stream. Asserted via an instrumented MinerCluster \
stub recording every accepted (tenant_id, OtlpLogRecord) pair."
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//! RFC0003.4 — Tenant resolution failure rejects the entire batch `[§3.7]`.
//!
//! Red gate (`specified → red`): `#[ignore]`'d until the receiver
//! lands.

/// Scenario RFC0003.4 — Tenant resolution failure rejects the entire batch.
/// See `docs/rfcs/0003-otlp-receiver.md` §5.
#[ignore = "RFC 0003 red gate — implementation pending (RFC0003.4)"]
#[test]
fn rfc0003_4_unresolvable_tenant_rejects_whole_batch() {
unimplemented!(
"RFC0003.4 — an export whose Resource attributes do not resolve to a \
configured tenant rule is rejected with a transport-level error naming \
the failing Resource and the missing attribute; no records are accepted \
and no OtlpBatch frame is appended (all-or-nothing per §6.3)."
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//! RFC0003.5 — gRPC ≡ HTTP/protobuf decode equivalence.
//!
//! Red gate (`specified → red`): `#[ignore]`'d until the receiver
//! lands.

/// Scenario RFC0003.5 — gRPC ≡ HTTP/protobuf decode equivalence.
/// See `docs/rfcs/0003-otlp-receiver.md` §5.
#[ignore = "RFC 0003 red gate — implementation pending (RFC0003.5)"]
#[test]
fn rfc0003_5_grpc_and_http_protobuf_decode_identically() {
unimplemented!(
"RFC0003.5 — a byte-equal protobuf payload delivered over gRPC and over \
HTTP/x-protobuf produces the identical in-memory ExportLogsServiceRequest \
(per §8, exercised by a proptest strategy over the proto value space)."
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//! RFC0003.6 — HTTP/JSON ↔ gRPC/protobuf equivalence with OTLP-JSON encoding rules.
//!
//! Red gate (`specified → red`): `#[ignore]`'d until the receiver
//! lands.

/// Scenario RFC0003.6 — HTTP/JSON ↔ gRPC/protobuf equivalence with OTLP-JSON encoding rules.
/// See `docs/rfcs/0003-otlp-receiver.md` §5.
#[ignore = "RFC 0003 red gate — implementation pending (RFC0003.6)"]
#[test]
fn rfc0003_6_json_decodes_to_the_same_anyvalue_tree_as_protobuf() {
unimplemented!(
"RFC0003.6 — a valid OTLP/JSON request (whitespace + field-ordering \
variation; hex trace/span IDs, base64 bytes, integer-valued enums, \
unknown fields ignored) decodes to the same in-memory AnyValue tree the \
same logical record produces over gRPC + protobuf. Equivalence asserted \
at the AnyValue level (canonicalisation is the storage layer's, per §6.4)."
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//! RFC0003.7 — `Body::Structured` carries the decoded `AnyValue` verbatim.
//!
//! Red gate (`specified → red`): `#[ignore]`'d until the receiver
//! lands.

/// Scenario RFC0003.7 — `Body::Structured` carries the decoded `AnyValue` verbatim.
/// See `docs/rfcs/0003-otlp-receiver.md` §5.
#[ignore = "RFC 0003 red gate — implementation pending (RFC0003.7)"]
#[test]
fn rfc0003_7_structured_body_reaches_miner_as_verbatim_anyvalue() {
unimplemented!(
"RFC0003.7 — a structured body reaches the miner as \
Body::Structured(AnyValue) structurally equal to the wire AnyValue (no \
canonicalisation, no reshape, no dropped fields), and the same equality \
holds across all three transports."
);
}
17 changes: 17 additions & 0 deletions crates/ourios-ingester/tests/rfc0003_8_body_string_lraw.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//! RFC0003.8 — `Body::String` reaches the miner as the unwrapped `L_raw`.
//!
//! Red gate (`specified → red`): `#[ignore]`'d until the receiver
//! lands.

/// Scenario RFC0003.8 — `Body::String` reaches the miner as the unwrapped `L_raw`.
/// See `docs/rfcs/0003-otlp-receiver.md` §5.
#[ignore = "RFC 0003 red gate — implementation pending (RFC0003.8)"]
#[test]
fn rfc0003_8_string_body_reaches_miner_unwrapped() {
unimplemented!(
"RFC0003.8 — a string body becomes OtlpLogRecord.body = \
Some(Body::String(s)) where s is the original UTF-8 string (no wrapping, \
quoting, or escaping); the value handed to MinerCluster::ingest equals s \
byte-for-byte (instrumented MinerCluster stub records the body argument)."
);
}
18 changes: 18 additions & 0 deletions crates/ourios-ingester/tests/rfc0003_9_edge_otlp_fields.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//! RFC0003.9 — Edge OTLP fields pass through unchanged.
//!
//! Red gate (`specified → red`): `#[ignore]`'d until the receiver
//! lands.

/// Scenario RFC0003.9 — Edge OTLP fields pass through unchanged.
/// See `docs/rfcs/0003-otlp-receiver.md` §5.
#[ignore = "RFC 0003 red gate — implementation pending (RFC0003.9)"]
#[test]
fn rfc0003_9_edge_otlp_fields_are_not_coalesced() {
unimplemented!(
"RFC0003.9 — severity_number = 0 (UNSPECIFIED) is kept as 0, scope_name = \
None, and wire observed_time_unix_nano = 0 maps to None (the Option<u64> \
conversion this scenario owns). The record is accepted by \
MinerCluster::ingest without rejection, coalescing, substitution, or \
downcast to a default."
);
}
Loading