code wiki / _hdl_build / nx_adnet_campaign.nx
nx_adnet_campaign.nx
buildroot/runtime/_hdl_build/nx_adnet_campaign.nx
about
nx_adnet_campaign.nx -- LIB: the CAMPAIGN, i.e. the decision "may this creative serve right now".
WHAT IT CLOSES: an advertiser record says WHO is buying and a rate card says AT WHAT PRICE, but nothing
in the plane says WHEN or HOW MUCH. Today an inventory row serves forever the moment it exists.
THE GAP THAT MOTIVATED THIS, MEASURED: anb_capped clamps the BILL at cap_milli but nothing stops the
SERVING. So an advertiser past budget keeps receiving impressions that can never be invoiced -- we give
away inventory and call it a cap. A budget ceiling that stops billing but not delivery is not a ceiling,
it is a discount that grows without limit.
★ THE DECISION IS A PURE FUNCTION OF (row, now, spent). No clock read, no file read, no global state --
so the gate can drive every branch deterministically and the edge can call it per request without IO.
★ FAIL-CLOSED ON MALFORMED: a row that cannot be EVALUATED is NOT servable. Never serve what you cannot
reason about; an unparseable campaign is exactly when you are least entitled to spend someone's money.
★ SEALED VERDICTS, never a bare boolean. "did not serve" and "did not serve BECAUSE the flight ended"
are different facts to an advertiser asking why their spend stopped, and a support answer needs the
second one.
Row contract (TAB-separated, same shape discipline as nx_adnet inventory):
<campaign_bk> <advertiser_bk> <creative_url> <start_epoch> <end_epoch> <budget_milli> <status>
status: live | paused end_epoch = -1 means OPEN-ENDED (an explicit fact, not a missing one)
budget_milli = -1 means NO BUDGET CEILING (again explicit; absent and unlimited must not look alike)
license_tier: ORIGINAL
dependencies 2 imports · 3 importers
imports: nx_syscalls.nxnx_adnet_slot.nx
imported by: nx_adnet_campaign_gate.nxnx_adnet_ops.nxnx_adnet_reconcile.nx
structs
| none |
consts
| 27 | const CAMP_SERVABLE: i64 = 1 |
| 28 | const CAMP_NOT_STARTED: i64 = 2 |
| 29 | const CAMP_ENDED: i64 = 3 |
| 30 | const CAMP_EXHAUSTED: i64 = 4 |
| 31 | const CAMP_PAUSED: i64 = 5 |
| 32 | const CAMP_MALFORMED: i64 = 6 |
| 36 | const CAMP_BAD_NUM: i64 = 0 - 999999999 |
functions
| 38 | func camp_num(s: *u8) -> i64 |
| 60 | func camp_verdict(row: *u8, rlen: i64, now: i64, spent_milli: i64) -> i64 |
| 105 | func camp_reason(v: i64, out: *u8) -> i64 |
| 138 | func camp_row_spent(row: *u8, rlen: i64) -> i64 |
| 146 | func camp_row_budget(row: *u8, rlen: i64) -> i64 |
| 152 | func camp_may_serve(camps: *u8, clen: i64, ad_id: *u8, now: i64) -> i64 |