Step 10 - Call the Standalone Activity
Call notifyRequester once the decision is final. From the caller's side there is nothing new to learn, which is the point of this step.
The caller cannot tell the difference
notifyRequester is called exactly like requestApproval: through the same generated stub, with the same Endpoint, the same type checking, and the same error handling. A caller in any language calls it the same way, as in step 6.
Nothing in the caller reveals that this Operation is backed by an Activity and the other by a Workflow. That is the contract doing its job. The handler team could later replace the notification Activity with a Workflow that retries across providers and escalates on failure, and no caller would change.
{sample code will be here}
Complete the flow
With all ten steps in place, the caller runs the whole approval:
- Call
checkApprovalRequired. It answers during the call, with nothing durable created. If the purchase is under the threshold, the flow stops here. - Call
requestApprovaland await it. The Operation starts the approval Workflow in the handler Namespace, or attaches to one that another Operation already started. - While it is pending, other systems call
remindApproverto nudge the approver andattachApprovalContextto add supporting information. - Someone calls
submitDecisionwithAPPROVEDorDENIED. The Update records it, confirms to that caller, and unblocks the approval Workflow. - The approval Workflow returns the decision, which resolves the
requestApprovalOperation every attached caller has been awaiting. - The caller calls
notifyRequesterwith the decision, backed by the notification Activity.
{sample code will be here}
Every step crossed a Namespace boundary, and the caller never learned a Workflow Id, a Task Queue, or which primitive backed any Operation. One Operation ran with no durable Execution at all, one started a Workflow, two sent messages to it, one started a Workflow if it was not already running, and one started an Activity — and from the caller's side they were all just Operations.
Trace it end to end
Open the caller Workflow in the UI and follow the links. Because the handlers used the Client rather than constructing their own, each Operation is connected to the Execution it started or messaged in the handler Namespace, and you can move between the two Namespaces in one view.
checkApprovalRequired is the exception, and not because anything is wrong: it started no Execution, so there is nothing on the handler side to link to. An Operation with no backing appears as a completed Operation and nothing more.
Where to go next
The Service is complete but minimal. Natural extensions:
- Timeouts and escalation. Give the approval a deadline and escalate or auto-deny when it passes.
- Split the Workers. Run the Nexus Service, the approval Workflow, and the notification Activity on separate Worker fleets. See Nexus patterns.
- Callers in other languages. Generate a caller from the same contract in Go, Python, or TypeScript. See Nexus Client Code Generator.
- Standalone invocation. Call an Operation from a Client with no caller Workflow. See Standalone Nexus Operation.
Before running this against anything real, read Debugging, common pitfalls, and tips.
Back to the Microservice Development Walkthrough overview.
- Nexus execution debugging for tracing across Namespaces.
- Nexus patterns for Worker and Service topology.
- Nexus Standalone Activity for Activity-backed Operations.