Skip to content

Add Exercise 1302: Async Nexus — fromWorkflowMethod() bridge between …#11

Open
nadvolod wants to merge 1 commit into
mmerrell:mainfrom
nadvolod:1302-nexus-async
Open

Add Exercise 1302: Async Nexus — fromWorkflowMethod() bridge between …#11
nadvolod wants to merge 1 commit into
mmerrell:mainfrom
nadvolod:1302-nexus-async

Conversation

@nadvolod

@nadvolod nadvolod commented Mar 2, 2026

Copy link
Copy Markdown
Collaborator

…1301 and 1300

Introduces one new concept on top of Exercise 1301 (sync Nexus): async Nexus via WorkflowClientOperationHandlers.fromWorkflowMethod().

The compliance handler now starts a real ComplianceInvestigationWorkflow instead of running inline. The Payments workflow holds a NexusOperationHandle and awaits it durably.

Structure:

  • exercise/ — student workspace with 7 TODO stub files (compiles clean)
  • solution/ — complete reference implementation (compiles clean)
  • ui/async-nexus-flow.html — interactive diagram with sync↔async toggle, kill-worker simulation, animated timeline
  • ui/sync-vs-async.html — conceptual comparison side-by-side
  • exercise-1302-README.md — 16-section guide with 5 checkpoints, 3-question quiz, "The Heist Test" durability demo

3 transactions: TXN-ALPHA (15s), TXN-BETA (35s), TXN-GAMMA (60s/BLOCKED)

…1301 and 1300

Introduces one new concept on top of Exercise 1301 (sync Nexus):
async Nexus via WorkflowClientOperationHandlers.fromWorkflowMethod().

The compliance handler now starts a real ComplianceInvestigationWorkflow
instead of running inline. The Payments workflow holds a
NexusOperationHandle<InvestigationResult> and awaits it durably.

Structure:
- exercise/ — student workspace with 7 TODO stub files (compiles clean)
- solution/ — complete reference implementation (compiles clean)
- ui/async-nexus-flow.html — interactive diagram with sync↔async toggle,
  kill-worker simulation, animated timeline
- ui/sync-vs-async.html — conceptual comparison side-by-side
- exercise-1302-README.md — 16-section guide with 5 checkpoints,
  3-question quiz, "The Heist Test" durability demo

3 transactions: TXN-ALPHA (15s), TXN-BETA (35s), TXN-GAMMA (60s/BLOCKED)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 2, 2026 20:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds Exercise 1302 (“Async Nexus”) to the curriculum as the bridge from Exercise 1301’s sync Nexus handler to an async Nexus pattern using WorkflowClientOperationHandlers.fromWorkflowMethod(), including a full student workspace, reference solution, and interactive UI diagrams.

Changes:

  • Introduces async Nexus integration where the Compliance handler starts a real workflow and Payments awaits via NexusOperationHandle.
  • Adds parallel starter runners + worker apps for the end-to-end demo (and “Heist Test” rerun).
  • Adds two HTML visualizations and a comprehensive step-by-step README guide.

Reviewed changes

Copilot reviewed 53 out of 53 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
exercise-1302-async-nexus/ui/sync-vs-async.html New side-by-side conceptual visualization contrasting sync vs async Nexus outcomes.
exercise-1302-async-nexus/ui/async-nexus-flow.html New interactive animated diagram showing async flow, sync toggle, and worker kill/restart simulation.
exercise-1302-async-nexus/exercise-1302-README.md New exercise guide with checkpoints, mental model, commands, and durability demo narrative.
exercise-1302-async-nexus/exercise/pom.xml Maven project for student workspace (Temporal SDK + exec runners).
exercise-1302-async-nexus/solution/pom.xml Maven project for reference solution (Temporal SDK + exec runners).
exercise-1302-async-nexus/exercise/src/main/java/shared/nexus/ComplianceNexusService.java Shared Nexus service contract for the student workspace (investigation operation).
exercise-1302-async-nexus/solution/src/main/java/shared/nexus/ComplianceNexusService.java Shared Nexus service contract for the reference solution (investigation operation).
exercise-1302-async-nexus/exercise/src/main/java/payments/PaymentGateway.java Student workspace simulated gateway for validation/execution.
exercise-1302-async-nexus/solution/src/main/java/payments/PaymentGateway.java Solution simulated gateway for validation/execution.
exercise-1302-async-nexus/exercise/src/main/java/payments/Shared.java Student workspace shared constants (task queue).
exercise-1302-async-nexus/solution/src/main/java/payments/Shared.java Solution shared constants (task queue).
exercise-1302-async-nexus/exercise/src/main/java/payments/domain/PaymentRequest.java Student workspace POJO for payment input.
exercise-1302-async-nexus/solution/src/main/java/payments/domain/PaymentRequest.java Solution POJO for payment input.
exercise-1302-async-nexus/exercise/src/main/java/payments/domain/PaymentResult.java Student workspace POJO for payment output/status.
exercise-1302-async-nexus/solution/src/main/java/payments/domain/PaymentResult.java Solution POJO for payment output/status.
exercise-1302-async-nexus/exercise/src/main/java/payments/temporal/activity/PaymentActivity.java Student workspace activity interface for payments.
exercise-1302-async-nexus/solution/src/main/java/payments/temporal/activity/PaymentActivity.java Solution activity interface for payments.
exercise-1302-async-nexus/exercise/src/main/java/payments/temporal/activity/PaymentActivityImpl.java Student workspace TODO stub for gateway-delegating activity implementation.
exercise-1302-async-nexus/solution/src/main/java/payments/temporal/activity/PaymentActivityImpl.java Solution implementation of payment activity delegating to gateway.
exercise-1302-async-nexus/exercise/src/main/java/payments/temporal/PaymentProcessingWorkflow.java Student workspace workflow interface for payment processing.
exercise-1302-async-nexus/solution/src/main/java/payments/temporal/PaymentProcessingWorkflow.java Solution workflow interface for payment processing.
exercise-1302-async-nexus/exercise/src/main/java/payments/temporal/PaymentProcessingWorkflowImpl.java Student workspace TODO stub demonstrating startNexusOperation + durable await pattern.
exercise-1302-async-nexus/solution/src/main/java/payments/temporal/PaymentProcessingWorkflowImpl.java Solution implementation orchestrating validate → async investigation → execute.
exercise-1302-async-nexus/exercise/src/main/java/payments/temporal/PaymentsWorkerApp.java Student workspace TODO stub wiring worker + Nexus endpoint mapping.
exercise-1302-async-nexus/solution/src/main/java/payments/temporal/PaymentsWorkerApp.java Solution payments worker wiring workflow, activities, and Nexus endpoint mapping.
exercise-1302-async-nexus/exercise/src/main/java/payments/temporal/PaymentStarter.java Student workspace starter launching 3 payments in parallel.
exercise-1302-async-nexus/solution/src/main/java/payments/temporal/PaymentStarter.java Solution starter launching 3 payments in parallel.
exercise-1302-async-nexus/exercise/src/main/java/payments/temporal/PaymentStarterRerun.java Student workspace rerun starter using timestamp-suffixed workflow IDs.
exercise-1302-async-nexus/solution/src/main/java/payments/temporal/PaymentStarterRerun.java Solution rerun starter using timestamp-suffixed workflow IDs.
exercise-1302-async-nexus/exercise/src/main/java/exercise/PaymentProcessingService.java Student workspace baseline “sync timeout problem” demo runner (Checkpoint 0).
exercise-1302-async-nexus/solution/src/main/java/exercise/PaymentProcessingService.java Solution baseline “sync timeout problem” demo runner (Checkpoint 0).
exercise-1302-async-nexus/exercise/src/main/java/compliance/SlowComplianceAgent.java Student workspace slow inline compliance pipeline used for the baseline timeout demo.
exercise-1302-async-nexus/solution/src/main/java/compliance/SlowComplianceAgent.java Solution slow inline compliance pipeline used for the baseline timeout demo.
exercise-1302-async-nexus/exercise/src/main/java/compliance/ComplianceInvestigator.java Student workspace compliance investigation logic with phase heartbeats.
exercise-1302-async-nexus/solution/src/main/java/compliance/ComplianceInvestigator.java Solution compliance investigation logic with phase heartbeats.
exercise-1302-async-nexus/exercise/src/main/java/compliance/domain/InvestigationRequest.java Student workspace POJO for investigation input.
exercise-1302-async-nexus/solution/src/main/java/compliance/domain/InvestigationRequest.java Solution POJO for investigation input.
exercise-1302-async-nexus/exercise/src/main/java/compliance/domain/InvestigationResult.java Student workspace POJO for investigation output.
exercise-1302-async-nexus/solution/src/main/java/compliance/domain/InvestigationResult.java Solution POJO for investigation output.
exercise-1302-async-nexus/exercise/src/main/java/compliance/temporal/activity/ComplianceInvestigationActivity.java Student workspace activity interface for compliance investigation.
exercise-1302-async-nexus/solution/src/main/java/compliance/temporal/activity/ComplianceInvestigationActivity.java Solution activity interface for compliance investigation.
exercise-1302-async-nexus/exercise/src/main/java/compliance/temporal/activity/ComplianceInvestigationActivityImpl.java Student workspace TODO stub for delegating compliance activity implementation.
exercise-1302-async-nexus/solution/src/main/java/compliance/temporal/activity/ComplianceInvestigationActivityImpl.java Solution implementation delegating to ComplianceInvestigator.
exercise-1302-async-nexus/exercise/src/main/java/compliance/temporal/ComplianceInvestigationWorkflow.java Student workspace workflow interface for compliance investigation.
exercise-1302-async-nexus/solution/src/main/java/compliance/temporal/ComplianceInvestigationWorkflow.java Solution workflow interface for compliance investigation.
exercise-1302-async-nexus/exercise/src/main/java/compliance/temporal/ComplianceInvestigationWorkflowImpl.java Student workspace TODO stub for compliance investigation workflow wiring.
exercise-1302-async-nexus/solution/src/main/java/compliance/temporal/ComplianceInvestigationWorkflowImpl.java Solution compliance investigation workflow invoking the investigation activity.
exercise-1302-async-nexus/exercise/src/main/java/compliance/temporal/ComplianceNexusServiceImpl.java Student workspace TODO stub for async Nexus handler via fromWorkflowMethod().
exercise-1302-async-nexus/solution/src/main/java/compliance/temporal/ComplianceNexusServiceImpl.java Solution async Nexus handler bridging operation → workflow start via fromWorkflowMethod().
exercise-1302-async-nexus/exercise/src/main/java/compliance/temporal/ComplianceWorkerApp.java Student workspace TODO stub for registering workflow/activity/Nexus handler on compliance worker.
exercise-1302-async-nexus/solution/src/main/java/compliance/temporal/ComplianceWorkerApp.java Solution compliance worker registering workflow, activity, and Nexus handler.
exercise-1302-async-nexus/exercise/src/main/java/compliance/temporal/InvestigationActivityTest.java Student workspace checkpoint runner (non-JUnit) for activity delegation.
exercise-1302-async-nexus/solution/src/main/java/compliance/temporal/InvestigationActivityTest.java Solution checkpoint runner (non-JUnit) for activity delegation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +585 to +588
Temporal **resumed from Phase 3** — it did not restart the investigation from Phase 1. Phase 1 and Phase 2 completion events were already written to the event log. The payment eventually completes.

> **This is what "durable" means.** A crash mid-operation is a deployment detail, not a failure.

Copilot AI Mar 2, 2026

Copy link

Choose a reason for hiding this comment

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

The "Heist Test" section claims the investigation resumes at Phase 3 and that earlier phases were already persisted/not re-run. With the current implementation (single ComplianceInvestigationActivity.investigate() activity), a worker crash will retry the entire activity from the beginning unless explicit heartbeat-resume logic is implemented. Please either adjust these expectations, or change the workflow/activity to checkpoint phases separately (multiple activities or heartbeat detail resumption).

Suggested change
Temporal **resumed from Phase 3** — it did not restart the investigation from Phase 1. Phase 1 and Phase 2 completion events were already written to the event log. The payment eventually completes.
> **This is what "durable" means.** A crash mid-operation is a deployment detail, not a failure.
Temporal kept the **workflow** and the in-flight investigation durable — the payment and its `ComplianceInvestigationWorkflow` were not lost, and they continued to completion once the worker came back.
With the sample implementation, all three phases run inside a single `ComplianceInvestigationActivity.investigate()` activity. If the worker crashes while that activity is running, Temporal will retry the activity, which means the investigation code may re-execute earlier phases unless you explicitly checkpoint progress (for example, by splitting phases into separate activities or using activity heartbeats with resume details).
> **This is what "durable" means here.** A crash mid-operation does not lose the workflow or the operation; Temporal will keep retrying until it completes or you tell it to stop.

Copilot uses AI. Check for mistakes.
Comment on lines +665 to +671
setStatus('running', 'Compliance worker restarted. Temporal resumes investigation from Phase 2...');

after(1500, () => {
document.getElementById('step5b').className = 'step visible active';
document.getElementById('step5btitle').textContent = 'Phase 2/3: Pattern Analysis (RESUMED)';
document.getElementById('step5bdetail').textContent = 'Temporal re-scheduled the activity. Phase 1 already recorded — not re-run!';
setStatus('running', '[INV-BETA] Resuming Phase 2/3 — Phase 1 was already persisted. Not re-run.');

Copilot AI Mar 2, 2026

Copy link

Choose a reason for hiding this comment

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

The restart path text says Temporal "resumes investigation from Phase 2" and that "Phase 1 already recorded — not re-run". With the current code (single long activity without heartbeat-detail resume), a crash will cause the activity to restart from the beginning on retry. Either implement resumable activity logic / per-phase activities, or update the UI copy to match actual behavior.

Copilot uses AI. Check for mistakes.
Comment on lines +63 to +73
long start = System.currentTimeMillis();
InvestigationResult result = activity.investigate(request);
long elapsed = (System.currentTimeMillis() - start) / 1000;

System.out.println("\n═══════════════════════════════════════════════════");
System.out.println(" RESULT:");
System.out.println(" Transaction: " + result.getTransactionId());
System.out.println(" Blocked: " + result.isBlocked());
System.out.println(" Risk Level: " + result.getRiskLevel());
System.out.println(" Summary: " + result.getSummary());
System.out.println(" Time: " + elapsed + " seconds");

Copilot AI Mar 2, 2026

Copy link

Choose a reason for hiding this comment

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

If activity.investigate(request) returns null (e.g., student hasn’t implemented the TODOs yet), this runner will throw a NullPointerException at result.getTransactionId() and won’t print the intended helpful failure message. Add an explicit null check on result (and exit with a clear message) before dereferencing it.

Copilot uses AI. Check for mistakes.
Comment on lines +86 to +90
} catch (Exception e) {
Workflow.getLogger(PaymentProcessingWorkflowImpl.class)
.error("Workflow failed for " + request.getTransactionId() + ": " + e.getMessage());
return new PaymentResult(false, request.getTransactionId(), "FAILED",
null, null, null, e.getMessage());

Copilot AI Mar 2, 2026

Copy link

Choose a reason for hiding this comment

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

The error logging drops the exception stack trace, which makes debugging workflow failures harder (especially in a teaching exercise). Consider logging the exception object as well (e.g., logger.error("...", e)) so root causes are visible in worker logs.

Copilot uses AI. Check for mistakes.
Comment on lines +34 to +39
@Override
public InvestigationResult investigate(InvestigationRequest request) {
Workflow.getLogger(ComplianceInvestigationWorkflowImpl.class)
.info("Starting 3-phase investigation for " + request.getTransactionId());
return activity.investigate(request);
}

Copilot AI Mar 2, 2026

Copy link

Choose a reason for hiding this comment

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

The investigation workflow currently calls a single long-running activity (activity.investigate(request)), so Temporal will retry that activity from the beginning after a worker crash. This contradicts the README/UI narrative that phases are checkpointed independently and the run resumes at a later phase (and that you’ll see multiple activity completions). If you want the “resume from last completed phase” demo, split the investigation into 3 separate activities (or implement activity resumption via heartbeat details) so each phase becomes its own durable checkpoint; otherwise, update the docs/UI to reflect that the whole activity restarts on retry.

Copilot uses AI. Check for mistakes.
Comment on lines +101 to +108
private void heartbeat(String phase) {
try {
// Heartbeat so Temporal knows the activity is still alive during long phases
Activity.getExecutionContext().heartbeat(phase);
} catch (Exception e) {
// Not running inside a Temporal activity (e.g., test runner) — ignore
}
}

Copilot AI Mar 2, 2026

Copy link

Choose a reason for hiding this comment

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

The activity heartbeats the current phase, but there’s no corresponding use of Activity.getExecutionContext().getHeartbeatDetails(...) to resume after a retry. As written, a crash mid-investigation will cause the activity to re-run Phase 1 again on retry, despite the exercise materials claiming it resumes without re-running earlier phases. Either implement resume logic based on heartbeat details (and make phases idempotent) or adjust the durability demo/docs accordingly.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants