refactor!: rename events and subscriptions to triggers - #277
Conversation
d92cadf to
7ab9674
Compare
a4b16a5 to
7522218
Compare
7ab9674 to
01faf6c
Compare
7522218 to
b586ec0
Compare
01faf6c to
db14fc1
Compare
5dcf7eb to
d93553a
Compare
|
Dropped the The package stays at 0.1.0 and breaking changes land on it until there is a tag. #150's compatibility baseline gets taken at that tag, which is the first moment a baseline means anything. Reverted in the WIT files, The rest of the rename is unchanged: this only undoes the version churn. |
d93553a to
812f826
Compare
A module reacts to a trigger; "subscription" is eth_subscribe's word for a transport the runtime mostly does not use for chain logs. One commit by construction: on-trigger is part of every component's exported type, so the world, the parser, and every guest move together. The chain-log trigger is renamed to event in the same commit: an event is the contract-emitted ABI-defined thing the trigger filters on, so the trigger name now agrees with its event_signature field and the sol_events macro instead of contradicting them one line apart. WIT: `world trigger-module` exports `on-trigger`; `variant trigger` carries `event(log)` (the record is `log`, with `chain-id` on it), `schedule(schedule-tick)` and `extension(extension-trigger)`. Manifest: `[[subscription]]` with `kind` becomes `[[trigger]]` with `on`; the kebab wire values are `block`, `event` and `schedule` (`chain-log` becomes `event`, `cron` becomes `schedule` with the expression under the `cron` key), and `event_signature` stays (it is the Solidity ABI hash). Parser and refusals: `TriggerKind`, `manifest::Trigger`, `MissingTriggerKind`, `InvalidTrigger`, `InvalidEventAddress`, `InvalidEventTopic`, `NonStringTriggerFilter`, `TriggerKindClaimed`, `UnknownTriggerKind`, `ChainTriggerNotPermitted` and `DeadHoldTriggers`; the pinned `error_kind` set respells without gaining a value. Supervisor: `subscription_plan` becomes `trigger_plan` returning a `TriggerPlan` whose event projection is `EventTrigger`, and the dispatch metric label `event_kind` becomes `trigger_kind` as ADR-0019 decides. Extension seam: `emits_trigger_kinds`, `open_sources`, `SourceContext`, `ExtensionDelivery` and `ExtensionSource`; videre and shepherd migrate under #262. SDK and macro: handlers `on_block`, `on_event`, `on_schedule`, `on_extension`; `subscribes(...)` becomes `sol_events(...)`, `nexum_sdk::events` becomes `nexum_sdk::sol_events` and `ChainLogParts` becomes `LogParts`. The chain transport keeps its RPC vocabulary (`watch_chain_logs`, the per-trigger log streams, `log_backfill_concurrency`), and the persisted store keys `chainlog_cursor:{keccak}` and `last_dispatched_block:{chain_id}` are unchanged. Docs: 02-modules-events-packaging.md becomes 02-modules-triggers-packaging.md with its source table rewritten. Closes #239 BREAKING CHANGE: the manifest table `[[subscription]]` with `kind` becomes `[[trigger]]` with `on`, and the wire values `chain-log` and `cron` become `event` and `schedule`; the WIT world `event-module` becomes `trigger-module` and its export `on-event` becomes `on-trigger`, so every guest rebuilds; the metric label `event_kind` becomes `trigger_kind` on `nexum_runtime_event_latency_seconds` and `nexum_runtime_dispatch_dropped_total`; the supervisor API `subscription_plan`, `SubscriptionPlan` and `ChainLogSub` become `trigger_plan`, `TriggerPlan` and `EventTrigger`. AI Assistance: Claude Fable 5 used for the implementation.
|
Folded in the The rename. The trigger variant is now The scope boundary, which is where this could have gone wrong. Renamed what an author declares and receives; left what describes how the host fetches from a node. Three exemptions held. The persisted key The label rename came with it, deliberately. Review found that leaving Also swept, since the retired vocabulary had survived in the supervisor API: 13 findings, 11 fixed, 2 rejected. The rejections:
|
812f826 to
f351a25
Compare
Closes #239.
What this is
A module reacts to a trigger. "Subscription" is
eth_subscribe's word for a transport the runtime mostly does not use, and "event" was doing three jobs at once. This renames the guest-facing vocabulary to one word before v1 freezes it.One commit by construction:
on-triggeris part of every component's exported type, so the world, the parser, the macro, the SDK and every guest have to move together.BREAKING CHANGE
This is the pre-v1 guest-ABI freeze. It breaks every layer a module author touches.
Every compiled guest
.wasmfails at instantiation until it is rebuilt.on-eventis part of a component's exported type, not a name the host looks up leniently, so an existing component no longer satisfies the world. The failure is at instantiation, before any handler runs.WIT.
world event-modulebecomesworld trigger-module, exportingon-trigger.variant eventbecomesvariant trigger, whose cases are nowblock(block),event(log),schedule(schedule-tick)andextension(extension-trigger { extension-kind, payload }).record chain-logsis deleted andchain-idmoves onto the log record.Manifest.
[[subscription]]withkind =becomes[[trigger]]withon =. The values are"block","event"and"schedule";"chain-log"and"cron"both refuse.Metric label.
event_kindbecomestrigger_kindat every emit site. Metric names are unchanged and belong to #243.Refusal labels. Roughly ten
error_kindvalues respell:missing_subscription_kind,invalid_subscription,non_string_subscription_filter,subscription_kind_claimed,unknown_event_kind,chain_subscription_not_permittedanddead_hold_subsbecome their trigger equivalents. The pinned set neither gains nor loses a value, but any alerting onerror_kindneeds its selectors updated.Operator messages. Six refusals are reworded, for example "manifest: [[subscription]] table {index} must declare a string
kind" becomes "manifest: [[trigger]] table {index} must declare a stringon".Public
Extensiontrait.subscriptions()becomesemits_trigger_kinds(),events()becomesopen_sources(),EventSourcesbecomesSourceContext(subscribedbecomesdemanded_extension_kinds),ExtensionEventbecomesExtensionDelivery { extension_kind, attrs, trigger },ExtensionEventStreambecomesExtensionSource.Supervisor API.
supervisor/subscriptions.rsbecomessupervisor/triggers.rs,subscription_plan()becomestrigger_plan(),SubscriptionPlanbecomesTriggerPlan,ChainLogSubbecomesEventTrigger.SDK and macro. Handlers are
init,on_block,on_event,on_schedule,on_extension.subscribes(...)becomessol_events(...), andnexum_sdk::eventsbecomesnexum_sdk::sol_events.Why
event(log)rather thanchain-logThe vocabulary contradicted itself one line apart: the trigger was
chain-logwhile its filter field isevent_signatureand the SDK macro issol_events. Those three now name one concept.In Ethereum vocabulary an event is precise, contract-emitted and ABI-defined, so it names a species of trigger rather than the genus, and a block is correctly not one. The chain is implied by context. The payload keeps the name
logbecause an event is what a contract emitted and a log is the record of it, which is whyeth_getLogsis spelled that way.Renaming the label followed necessarily. Leaving
event_kindwhile its value became"event"would emitevent_kind="event", asserting that "event" is both the genus and one of its species: the same self-contradiction this rename removes, moved one layer up. ADR-0019 already requiredtrigger_kind, so it lands here rather than breaking the same dashboards twice.The scope boundary
This renames what an author declares and receives. It does not rename how the host fetches from a node, where "log" is the correct RPC word.
Left alone deliberately:
ProviderPool::watch_chain_logs,open_chain_log_streams,push_chain_log,CanonicalLogBatch,TaggedChainLog,log_backfill_concurrency, and thestream_reconnects_totallabelkind = "chain-log", which names the RPC stream rather than a trigger.No shim, no alias, no migration hint
No compatibility shim, no type alias, no deprecated re-export, no refusal text mentioning the old spelling.
The project is pre-release, so nobody is owed a deprecation window. An unmigrated
[[subscription]]already refuses loudly: the parser reports the section unclaimed and boot stops, which is the whole diagnosis a reader needs. A refusal explaining what a key used to be called is cruft that outlives the migration by years.Deliberately unchanged
nexum:hoststays at0.1.0. Nothing is published, so the version denotes nothing to anyone and there is no consumer pinned to 0.1.0 to protect. Breaking changes land on it until there is a tag. #150 takes its compatibility baseline at that tag, which is the first moment a baseline is meaningful.event_signatureis untouched. It is the Solidity ABI hash: "event" there is the EVM's noun, and it now agrees with the trigger name instead of contradicting it.The persisted store keys are byte-identical:
last_dispatched_block:{chain_id}andchainlog_cursor:{keccak}.cursors.rsdoes not appear in the diff at all. A vocabulary rename must not orphan operator data, and the data-compat tests pinning both derivations pass untouched.Downstream
videreandshepherdimplement theExtensiontrait and are broken by this. Both are already unbuildable againstmainfor unrelated reasons, so this adds no new blockage. Their migration is #262.Review
Two rounds, 23 findings, 20 fixed and 3 rejected.
First round, ten findings, all minor. Stale
event-modulein theCORE_NAMESPACErustdoc; anexum-sdk/Cargo.tomlcomment pointing at the deletedeventsmodule; the publishednexum-module-macrosdescription still saying "event dispatch"; six fixtureCargo.tomldescriptions and aflaky-bomb/component.tomlcomment left on the retired vocabulary while their manifests moved; two sentences in the Dispatch section ofdocs/02still calling the dispatched value an event; and three cases of comment growth, all trimmed back to their pre-rename length.Rejected: present-tense
on-eventin ADR-0022 andevent-modulein ADR-0020. ADRs are dated records; #239 enumerates the ADR edits exactly and neither is in that list, and ADR-0019 is itself the record deciding this rename and quotes every retired spelling. The sweep targets live surfaces, not decision records.Second round, thirteen findings, two major. The
event_kindlabel, described above. The retired "subscription" vocabulary surviving in the supervisor API, now swept. Plus ADR-0019's Decision line still naming the old core set, adocs/02row carrying an unsupported release claim, an oversimplified retired-kind test rewritten against a realistic stale manifest, a missingBREAKING CHANGEfooter, and three comment-noise items.Rejected: renaming
LogSourceandManifestSource, because ADR-0019 schedules the remaining source renames for later issues andLogSourcealso names a live tracing field; and one cited ADR line that the transport-layer exemption leaves true.Verification
just cigreen: content lint, zero-leak, MSRV, fmt, clippy under-D warnings, rustdoc, all twelve release wasms rebuilt, 783/783 nextest, doctests.TriggerKind::VARIANTSis["block", "event", "schedule"], and"chain-log"and"cron"are both pinned as refusing.AI Assistance: Claude Fable 5 and Claude Opus 5 used for the implementation, review, and this description.