Skip to content

[Draft] Add support for standalone callbacks#10192

Draft
chrsmith wants to merge 5 commits intomainfrom
chrsmith/standalone-callbacks_ii
Draft

[Draft] Add support for standalone callbacks#10192
chrsmith wants to merge 5 commits intomainfrom
chrsmith/standalone-callbacks_ii

Conversation

@chrsmith
Copy link
Copy Markdown
Contributor

@chrsmith chrsmith commented May 7, 2026

ℹ️ This PR is a rebase and cleanup from an earlier prototype, #9805.

⚠️ This is dependent on changes in the api and api-go repos. And will need some care before merging.

What changed?

Adds support for "standalone" callbacks. Today, the CHASM Callback component is used to deliver an arbitrary payload to a URL. (e.g. when a Workflow has completed.) As part of supplying the Nexus Connector Foundations, this feature adds CRUD operations on callbacks directly. So callers can invoke StartCallbackExecution(...) and get the durability guarantees to ensure that the callback actually gets invoked.

Why?

The primary (only?) use-case for this is for completing Nexus operations. With this capability, a Handler can implement a Nexus operation outside of Temporal. And when that operation completes, simply call StartCallbackExecution(...) with the right callback URL and Token. Then the CHASM Callback machinery will attempt to deliver the result for the Nexus operation. (Rather than, say, the Nexus operation to be implemented as a Workflow that is separately polling the async or out-of-band process.)

How did you test it?

  • built
  • run locally and tested manually
  • covered by existing tests
  • added new unit test(s)
  • added new functional test(s)

Potential risks

TBD. Will need to ask around.

@chrsmith chrsmith force-pushed the chrsmith/standalone-callbacks_ii branch 2 times, most recently from 0d3b36b to ad9f7cb Compare May 7, 2026 21:21
@chrsmith chrsmith changed the title [Draft] Standalone Callbacks - II [Draft] Add support for standalone callbacks May 7, 2026
@stephanos stephanos self-requested a review May 7, 2026 21:37
@chrsmith chrsmith requested a review from Quinn-With-Two-Ns May 7, 2026 21:40
@chrsmith chrsmith force-pushed the chrsmith/standalone-callbacks_ii branch from edb387a to 40f2f7e Compare May 7, 2026 22:01
Comment thread chasm/lib/callback/statemachine.go
Comment thread chasm/lib/callback/library.go
"/temporal.api.workflowservice.v1.WorkflowService/PollNexusOperationExecution": 4,
"/temporal.api.workflowservice.v1.WorkflowService/PollActivityExecution": 4, // TODO(saa-preview): should it be 4 or 3?
"/temporal.api.workflowservice.v1.WorkflowService/PollActivityExecution": 4, // TODO(saa-preview): Should it be 4 or 3? Same PollCallback.
"/temporal.api.workflowservice.v1.WorkflowService/PollCallbackExecution": 4,
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.

it seems the other APIs added Poll and Describe to ExecutionAPICountLimitOverride?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch! Yes, it looks like they do. I only updated this file because some unit tests failed, but it looks like there's some more meaningful choices to consider.

I'll take a closer look and pattern things after the Activity endpoints, since we'd want to modify how the Callback APIs are counted for the same reasons.

cb.recordAttempt(event.Time)
now := ctx.Now(cb)
cb.recordAttempt(now)
cb.LastAttemptFailure = nil
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.

This should set CloseTime as it's a terminal state. Also could to have covered by a test somewhere.

type library struct {
componentOnlyLibrary

config *Config
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.

This seems to be unused?

return missingRequiredFieldError("Namespace")
}
return nil
}
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.

Some things I'm missing:

  • is the run_id validation; see use of uuid.Validate
  • identity length validation
  • reason length validation
  • SANO also has a if ref.NamespaceID != namespaceID check for the polling token

if completion.GetSuccess() != nil && completion.GetFailure() != nil {
return serviceerror.NewInvalidArgument("Completion must have exactly one of success or failure set, not both.")
}
// Validate the size of the completion is reasonable.
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.

nit: I don't think this comment adds anything, the method name is already very expressive

return missingRequiredFieldError("Namespace")
}
return nil
}
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.

I'm not seeing any tests for the validations. I think those are valuable. See temporal/chasm/lib/nexusoperation/validator_test.go for an example.

}

// ScheduleToCloseTimeout
if req.GetScheduleToCloseTimeout() == nil || req.GetScheduleToCloseTimeout().AsDuration() <= 0 {
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.

I wonder if we want a MaxOperationScheduleToCloseTimeout? SANO has it.

}
}

// Create the CHASM Callback in so-called "standalone" mode, where it will be the root
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.

nit: I don't think we need "so-called" and quotes; "standalone" for all the standalone features is part of the public-facing wording.

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