Add OCI Notifications: topics and subscriptions - #421
Conversation
Implements OCI Notifications against the portable notification driver. providers/oci/notifications: a Mock over memstore.Store guarded by a single RWMutex. Topics carry an ocid1.onstopic OCID, a compartment recorded at create and filtered on every list, a short topic id, lifecycle state, etag and creation time. Subscriptions carry an ocid1.onssubscription OCID and start PENDING with a confirmation token; a publish reaches only ACTIVE ones, so an unconfirmed endpoint receives nothing. Deleting a topic takes its subscriptions with it, as ONS does. server/oci/notifications: the /20181201 wire handler for topics, subscriptions, the two token-authenticated confirmation endpoints, the changeCompartment and resendConfirmation actions, and PublishMessage on the topic's own endpoint. Real ONS splits control and data plane by host rather than by prefix, so a topic reports the requesting origin as its apiEndpoint and a publish lands back on the same listener. DeleteTopic is asynchronous: it records a work request and answers 204 with opc-work-request-id. The OCI-only surface — subscription compartments, tags, metadata, delivery policy, the confirmation handshake and a topic's lifecycle state — is declared consumer-side as an Extras interface in the handler, with its value types in the provider. A driver that does not satisfy it is served 501. Nothing was added to services/notification/driver. Input the emulator cannot honour is refused rather than stored unused: message attributes, defined tags, protocols outside the ONS set, unknown message types and unsupported sort keys all answer 400 naming what is unsupported.
NitinKumar004
left a comment
There was a problem hiding this comment.
Review notes
Real data-plane engine (per #427): N/A.
Findings
Medium · docs — docs/services.md not updated with OCI Notifications — unmet Definition-of-done checkbox
docs/services.md:23
If a user consults docs/services.md (the human-facing service catalog) to learn what OCI surface CloudEmu emulates -> they find no ONS topics/subscriptions/publish entry and conclude the service is unimplemented, because the vertical slice's documentation step was skipped even though the code and generated coverage exist.
git diff merge-base..HEAD shows docs/services.md untouched; only auto-generated docs/coverage/* changed. oci-conventions.md 'Definition of done' requires 'Operations added to docs/services.md', and sibling OCI services each have a hand-written section (OCI Monitoring line 623, OCI identity line 749, OCI VCN note line 407). Notifications has none.
Low · structure — Per-feature filename not mirrored across provider/wire layers for topics and publish
providers/oci/notifications/publish.go:1
If a maintainer greps for the publish feature by filename (publish.go) -> they find only the provider side and miss that the wire implementation lives in topics.go, because the feature file name is not mirrored on the wire layer; a navigation cost, not a behavioral defect.
STRUCTURE.md §3: 'A feature uses the same filename across all three layers.' subscriptions.go matches (provider+wire), but topic CRUD is provider notifications.go vs wire topics.go, and publish is provider publish.go vs wire (folded into topics.go). provider notifications.go is defensible as the §4 .go core-CRUD file, but publish.go/topics.go breaks the one-grep goal.
Summary
notificationdriver.services/notification/driver— OCI-only behaviour is a consumer-sideExtrasinterface, per the rule set in Move OCI-only capabilities out of shared driver packages #393.Closes #415. Part of #376.
Changes
providers/oci/notifications/—Mockovermemstoreimplementingdriver.Notification, guarded by async.RWMutex.server/oci/notifications/— the/20181201/surface. Topics: Create/Get/List/Update/Delete/ChangeCompartment. Subscriptions: Create/Get/List/Update/Delete/Confirm/Unsubscribe/ResendConfirmation/ChangeCompartment. Data plane: PublishMessage.providers/oci/oci.goandserver/oci/oci.go.The confirmation flow
CreateSubscriptionmints an OCID, setslifecycleState: PENDINGand a confirmation token. Real ONS mails the token to the endpoint; the emulator has no channel, so the token rides back in the response body and is dropped once the subscription is ACTIVE.GET /subscriptions/{id}/confirmationvalidates token and protocol, flips to ACTIVE, and returns anunsubscribeUrlpointing at this emulator's own origin.PublishMessageskips anything not ACTIVE, so a publish to a PENDING subscription delivers to nobody — asserted at both driver and wire layers, and visible in the transcript below.Two corrections to the issue as written
apiEndpoint), both on/20181201. Implemented asPOST /20181201/topics/{id}/messages, with every topic reporting the requesting origin as itsapiEndpoint, so an SDK pointed at the returned endpoint lands back on the same listener.DeleteTopicreturns 204, not 202. Real ONS answers204with anopc-work-request-id.docs/oci-conventions.md's generic 202 is the common case, not ONS's. The work request is still recorded and pollable.Never accept-and-ignore
Refused with a named 400 rather than silently dropped: message attributes (ONS has no such field),
definedTags, protocols outside the ONS set, unknownmessageType, unsupportedsortBy/sortOrder. Protocol aliases (email,https→CUSTOM_HTTPS) are mapped, not dropped.Provider Coverage
Checklist
go test ./...) — see note belowgolangci-lint run --timeout=9m) — 0 issuescloudemu_test.go— driver + handler tests insteadTest Plan
Correction on a suite note. An earlier run of this branch showed
cmd/cloudemu TestServeOutOfProcessfailing, and I first attributed it to the sandbox. That was wrong. It is contention on the shared~/.cloudemudaemon lock between the six Wave 2 worktrees running their suites in parallel — self-inflicted, not a repo bug. Re-run with nothing else running, the whole suite is exit 0 including that test.Coverage leak check clean: no OCI operation appears in
docs/coverage/{aws,azure,gcp}/*.md, andgit diff development -- services/is empty.End-to-end on a running server (port 4616):
Left out
No
oci-go-sdkcompat test — the SDK splits ONS across two clients with a host override, needing more scaffolding than it would buy; wire shapes are asserted field-by-field instead. Publishing records deliveries rather than pushing to real HTTPS/email endpoints, matching howproviders/aws/snshandles non-SQS protocols.definedTagsis refused rather than modelled, consistent with the rest of the OCI surface.