Skip to content

[Nexus] Support internal callback completion routing to CHASM - #8372

Merged
lina-temporal merged 18 commits into
mainfrom
nexus-chasm
Oct 16, 2025
Merged

lina-temporal merged 18 commits into
mainfrom
nexus-chasm

Conversation

@lina-temporal

@lina-temporal lina-temporal commented Sep 23, 2025 •

Copy link
Copy Markdown
Contributor

What changed?

  • The Callbacks component now detects Nexus URLs of the form temporal://internal/chasm, which are routed to CHASM components through a new ChasmInvocation.
    • CHASM routing information is serialized into a header, the URL is left opaque.
  • A new CHASM interface has been added, chasm.NexusCompletionHandler, which components can implement to receive Nexus callbacks.
  • A CHASM helper method, GetNexusCallback, has been added that returns a Callback protobuf routing to the given component.
  • The frontend's callback argument validator has been patched to allow "temporal" schemes unconditionally. Scheduler starts workflows through the frontend, in order to be counted by metering, and so frontend must allow requests with internal-facing callbacks.
    • I believe @chaptersix 's changes also touch this area, we may not need my interim patch there.

Why?

  • CHASM Scheduler needs to find out about workflow completions, and we want to do that with Nexus completion callbacks.

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

  • The funkiness is in the frontend handler - see the TODO. I don't think it presents a security risk, since a customer would only be able to forge completions within their own namespace (since this validation takes place within StartWorkflowExecution's frontend flow). But it would be nice to validate that it was only coming from internal pods.

@lina-temporal
lina-temporal requested a review from a team as a code owner September 23, 2025 22:23
Comment thread chasm/nexus_completion.go Outdated
NexusComponentRefHeader = "X-CHASM-Component-Ref"

// Base URL for Nexus->CHASM callbacks.
NexusCompletionHandlerURL = "temporal://internal/chasm"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
NexusCompletionHandlerURL = "temporal://internal/chasm"
NexusCompletionHandlerURL = "temporal://internal"

Comment thread chasm/nexus_completion.go Outdated

const (
// Header name for the CHASM ComponentRef.
NexusComponentRefHeader = "X-CHASM-Component-Ref"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No need, just put this in the callback token header.

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.

When I synced up with @chaptersix , we decided to use SystemCallbackURL so it goes through the same handler as other internal callbacks, which I think makes sense. However, if we don't have a unique URL nor a unique CHASM header, how would we distinguish this as a CHASM request in the callback executor?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We are thinking of deprecating the callback headers for the most part, which is why I would ask that you use a single token field.

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.

Moved to the commonnexus.CallbackTokenHeader field. Relies on temporal://internal being unique to CHASM.

if err != nil {
return err
}
case *persistencespb.Callback_Hsm:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can just remove this branch and the rest of the code it references.

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.

Sure, I'll open a separate PR to remove the Callback_Hsm invocation stuff.

Comment thread components/callbacks/executors.go Outdated
chasmInvokable := chasmInvocation{}
chasmInvokable.nexus = variant.Nexus
chasmInvokable.attempt = callback.Attempt
invokable = chasmInvokable

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You're going to want to set the completion on here too...

Would you also please just set all of the fields here inline with the struct definition?
Could just do:

invokable = chasmInvocation{
  nexus: variant.Nexus,
  ...
}

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.

Oops, yeah, cleaned these up.

Comment thread components/callbacks/executors.go Outdated
}

// variant struct is immutable and ok to reference without copying
nexusInvokable := nexusInvocation{}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same here, would be nice to just inline the whole field assignment (unrelated to your change).

// this similarly as we would a pure task (holding an exclusive lock), as the
// assumption is that the accessed component will be recording (or generating a
// task) based on this result.
_, err = e.ChasmEngine.UpdateComponent(ctx, ref, func(ctx chasm.MutableContext, component chasm.Component) error {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This doesn't do an RPC, you're going to have to add an RPC to the shard that owns the execution of the original caller.
We can then optimize it so if the ref is something that we can resolve locally we would bypass the RPC call.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The RPC would be historyservice.CompleteNexusOperation, you'll want to update that method to invoke ChasmEngine.UpdateComponent and take a different form of completion.

Feel free to rename the completion field to hsm_completion to disambiguate between HSM and CHASM refs.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Let's also not change the Nexus RPC stuff for now since we are not using that SDK for delivering the completions.

We can change it later when the SDK supports pluggable transports if we want to but that's probably not critical.

Comment thread service/frontend/workflow_handler.go Outdated
}
// Internally routed.
// TODO - validate requests involving this URL come from a history pod.
if u.Scheme == "temporal" {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@chaptersix will take care of this, he's modifying this code right now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We need to validate that the caller is from within the cluster if it tries to attach a callback with an internal URL.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You need to merge your code with main (or rebase if you prefer :))

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.

I'll do that now that the stacked PRs are merged.

Comment thread chasm/nexus_completion.go Outdated
Comment on lines +15 to +16
// Base URL for Nexus->CHASM callbacks.
NexusCompletionHandlerURL = "temporal://system/nexus/callback/chasm"

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.

I'm still planning to get rid of this and use the constant SystemCallbackURL, but this branch is stacked on top of others, so I'll do that after others have merged in.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would consider using temporal://internal to avoid having to unpack the callback tokens.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

A good reason to use temporal://internal callbacks is because they will trip a separate circuit breaker in the outbound queue.
We should also consider running these callbacks on the immediate "transfer" queue instead and avoid using circuit breakers altogether but let's add an issue for this, we are going to refactor callbacks to use CHASM soon and can do this work as part of that.

@lina-temporal
lina-temporal requested a review from bergundy October 1, 2025 02:15
Comment thread chasm/nexus_completion.go Outdated

const (
// Header name for the CHASM ComponentRef.
NexusComponentRefHeader = "X-CHASM-Component-Ref"

ghost Oct 1, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We are thinking of deprecating the callback headers for the most part, which is why I would ask that you use a single token field.

Comment thread chasm/nexus_completion.go Outdated
Comment on lines +15 to +16
// Base URL for Nexus->CHASM callbacks.
NexusCompletionHandlerURL = "temporal://system/nexus/callback/chasm"

ghost Oct 1, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would consider using temporal://internal to avoid having to unpack the callback tokens.

Comment on lines +47 to +77
func (c chasmInvocation) Invoke(ctx context.Context, ns *namespace.Namespace, e taskExecutor, task InvocationTask) invocationResult {
// Get back the base64-encoded ComponentRef from the header.
encodedRef, ok := c.nexus.GetHeader()[chasm.NexusComponentRefHeader]
if !ok {
return invocationResultFail{errors.New("callback missing CHASM header")}
}

decodedRef, err := base64.RawURLEncoding.DecodeString(encodedRef)
if err != nil {
return invocationResultFail{fmt.Errorf("failed to decode CHASM ComponentRef: %v", err)}
}

ref := &persistencespb.ChasmComponentRef{}
err = proto.Unmarshal(decodedRef, ref)
if err != nil {
return invocationResultFail{fmt.Errorf("failed to unmarshal CHASM ComponentRef: %v", err)}
}

request, err := c.getHistoryRequest(ref)
if err != nil {
return invocationResultFail{fmt.Errorf("failed to build history request: %v", err)}
}

// RPC to History for cross-shard completion delivery.
_, err = e.HistoryClient.CompleteNexusOperationChasm(ctx, request)
if err != nil {
return invocationResultRetry{fmt.Errorf("failed to complete Nexus operation: %v", err)}
}

return invocationResultOK{}
}

ghost Oct 1, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Are these internal errors ever exposed to users or is this all internal?

ghost Oct 1, 2025

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.

This is internal-facing, for operators who are log-diving.


func (c chasmInvocation) WrapError(result invocationResult, err error) error {
if failure, ok := result.(invocationResultFail); ok {
return queues.NewUnprocessableTaskError(failure.err.Error())

ghost Oct 1, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This will prevent the task from being retried, is that what you are trying to do here? Doesn't seem like it...

ghost Oct 1, 2025

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.

Yes, that's what I'm trying to do; the errors I've marked as 'fail' explicitly are non-retryable (e.g., fails validation checks).

ghost Oct 6, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I see. That's fine. I think you just don't want to wrap in a destination down error though to avoid triggering the circuit breaker.

ghost Oct 9, 2025

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.

Updated to not wrap in DestinationDown.

return nil, fmt.Errorf("failed to convert Nexus links: %v", err)
}

payload, err := io.ReadAll(op.Reader)

ghost Oct 1, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Use proto.Unmarshal into common.Payload message here. And consider that the payload may be nil.

// ChasmNexusCompletion includes details about a completed Nexus operation.
message ChasmNexusCompletionInfo {
// Operation state - may only be successful / failed / canceled.
string state = 1;

ghost Oct 1, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

As mentioned the oneof is enough.

}

// ChasmNexusCompletion includes details about a completed Nexus operation.
message ChasmNexusCompletionInfo {

ghost Oct 1, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Info is redundant IMHO.

ghost Oct 2, 2025

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.

It's to disambiguate against the token, ChasmNexusCompletion; I could suffix that instead, maybe?

ghost Oct 6, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suffix how?

ghost Oct 8, 2025

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.

Renamed to ChasmNexusCompletion.

Comment thread service/frontend/workflow_handler.go Outdated
}
// Internally routed.
// TODO - validate requests involving this URL come from a history pod.
if u.Scheme == "temporal" {

ghost Oct 1, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You need to merge your code with main (or rebase if you prefer :))

_, err := h.chasmEngine.UpdateComponent(ctx, ref, func(ctx chasm.MutableContext, component chasm.Component) error {
handler, ok := component.(chasm.NexusCompletionHandler)
if !ok {
return serviceerror.NewUnimplementedf("component '%T' does not implement NexusCompletionHandler", component)

ghost Oct 1, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Will the caller consider this a retryable error? We should verify that it doesn't because the callback executor will just spin indefinitely.

ghost Oct 1, 2025

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 point, yeah the ChasmInvocation shouldn't be retrying on this.

Comment thread chasm/nexus_completion.go Outdated
Comment on lines +15 to +16
// Base URL for Nexus->CHASM callbacks.
NexusCompletionHandlerURL = "temporal://system/nexus/callback/chasm"

ghost Oct 1, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

A good reason to use temporal://internal callbacks is because they will trip a separate circuit breaker in the outbound queue.
We should also consider running these callbacks on the immediate "transfer" queue instead and avoid using circuit breakers altogether but let's add an issue for this, we are going to refactor callbacks to use CHASM soon and can do this work as part of that.

@lina-temporal
lina-temporal requested a review from bergundy October 2, 2025 22:46

ghost left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Didn't have a lot left to add. This is very close to ready.

) (*historyservice.CompleteNexusOperationChasmRequest, error) {
var req *historyservice.CompleteNexusOperationChasmRequest

token := &tokenspb.NexusOperationChasmCompletion{

ghost Oct 6, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: call this variable completion?

Comment on lines +118 to +123
req = &historyservice.CompleteNexusOperationChasmRequest{
Completion: token,
Outcome: &historyservice.CompleteNexusOperationChasmRequest_Failure{
Failure: apiFailure,
},
CloseTime: timestamppb.New(op.CloseTime),

ghost Oct 6, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: you could just set the outcome here and initialize the request outside of the switch statement.

ghost Oct 8, 2025

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.

I thought so too, but CloseTime is independent on both CompletionSuccess/CompletionFailure variants, so you have to type assert for that as well anyways.

// Complete an async Nexus Operation using a completion token. The completion state could be successful, failed, or
// canceled.
//
// Deprecated. Will be renamed to CompleteNexusOperationHsm in a future release.

ghost Oct 6, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not to start using it, but have it defined already. You need two versions to safely point the client to use the new API.

}

// ChasmNexusCompletion includes details about a completed Nexus operation.
message ChasmNexusCompletionInfo {

ghost Oct 6, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suffix how?

}

// A completion token for a Nexus operation started from a CHASM component.
message NexusOperationChasmCompletion {

ghost Oct 6, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hmm... can we merge this into the existing NexusOperationCompletion and deprecate the original fields?

You can just add a component_ref field and it would work well.

Not critical but it would simplify the decoding later.

ghost Oct 8, 2025

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.

Sure, moved to that.

// this similarly as we would a pure task (holding an exclusive lock), as the
// assumption is that the accessed component will be recording (or generating a
// task) based on this result.
_, err := h.chasmEngine.UpdateComponent(ctx, ref, func(ctx chasm.MutableContext, component chasm.Component) error {

ghost Oct 6, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Use chasm.UpdateComponent and avoid casting. If you merge the current main changes, you'll see that the chasm engine should already be on the request context.

ghost Oct 8, 2025

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.

Use chasm.UpdateComponent and avoid casting

I don't think I can do that here in a way that keeps this generic. I'm using the NexusCompletionHandler interface which doesn't bundle in Component, therefore, if I try to accept a NexusCompletionHandler here, it won't meet the generic requirements of implementing Component's LifecycleState.

ghost Oct 8, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That sounds like a bug in CHASM. You shouldn't need to inspect the type. There's no reason that chasmEngine.UpdateComponent would work and chasm.UpdateComponent(ctx) would not work.

ghost Oct 9, 2025

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.

What component type would you expect I use here? NexusCompletionHandler won't work since it isn't a Component.

ghost Oct 10, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That's what I expect, that you can use the interface instead of a concrete type.

@lina-temporal
lina-temporal requested a review from bergundy October 8, 2025 20:29

ghost left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is pretty close to done AFAIC.

}

if retry, ok := result.(invocationResultRetry); ok {
return queues.NewDestinationDownError(retry.err.Error(), err)

ghost Oct 8, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
return queues.NewDestinationDownError(retry.err.Error(), err)
return err

return err
}

func (c chasmInvocation) Invoke(ctx context.Context, ns *namespace.Namespace, e taskExecutor, task InvocationTask) invocationResult {

ghost Oct 8, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thinking about this some more, we shouldn't expose these errors. They are user visible. I suggest that instead we follow this pattern.

referenceID := uuid.NewString()
e.Logger.Error("failed to decode CHASM ComponentRef", tag.Error(err), tag.NewStringTag("reference-id", referendID))
return invocationResultFail{fmt.Errorf("internal error, reference-id: %v", referenceID)}

Same for invocationResultRetry

{
name: "success-with-successful-operation",
setupHistoryClient: func(t *testing.T, ctrl *gomock.Controller) *historyservicemock.MockHistoryServiceClient {
client := historyservicemock.NewMockHistoryServiceClient(ctrl)

ghost Oct 8, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Unrelated to this PR but I couldn't help myself. Really the whole mock and codegen here is redundant, this is so much simpler:

type MockHistoryClient struct {
  historyservice.HistoryServiceClient
  HandleCompleteNexusOperationChasm func(ctx context.Context, req *historyservice.CompleteNexusOperationChasmRequest, opts ...grpc.CallOption) (*historyservice.CompleteNexusOperationChasmResponse, error)
}

requestID string
}

var ErrUnimplementedHandler = serviceerror.NewUnimplemented("component does not implement NexusCompletionHandler")

ghost Oct 8, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this used?

ghost Oct 9, 2025

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.

Nope, got rid of it.

Comment thread proto/internal/temporal/server/api/historyservice/v1/request_response.proto Outdated
Comment on lines +105 to +106
// ChasmNexusCompletion includes details about a completed Nexus operation.
message ChasmNexusCompletion {

ghost Oct 8, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
// ChasmNexusCompletion includes details about a completed Nexus operation.
message ChasmNexusCompletion {
// NexusCompletion includes details about a completed Nexus operation.
message NexusCompletion {

ghost Oct 9, 2025

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.

Every other type in this protobuf is prefixed with Chasm, I'd rather keep that consistent or change all at once.

ghost Oct 10, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's not CHASM specific, you can move this somewhere else but not blocking the PR.

// this similarly as we would a pure task (holding an exclusive lock), as the
// assumption is that the accessed component will be recording (or generating a
// task) based on this result.
_, err := h.chasmEngine.UpdateComponent(ctx, ref, func(ctx chasm.MutableContext, component chasm.Component) error {

ghost Oct 8, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That sounds like a bug in CHASM. You shouldn't need to inspect the type. There's no reason that chasmEngine.UpdateComponent would work and chasm.UpdateComponent(ctx) would not work.

Lina Jodoin and others added 2 commits October 9, 2025 13:04
…esponse.proto

Co-authored-by: Roey Berman <roey@temporal.io>
@lina-temporal
lina-temporal requested a review from bergundy October 9, 2025 20:05
Comment on lines +105 to +106
// ChasmNexusCompletion includes details about a completed Nexus operation.
message ChasmNexusCompletion {

ghost Oct 10, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's not CHASM specific, you can move this somewhere else but not blocking the PR.

// this similarly as we would a pure task (holding an exclusive lock), as the
// assumption is that the accessed component will be recording (or generating a
// task) based on this result.
_, err := h.chasmEngine.UpdateComponent(ctx, ref, func(ctx chasm.MutableContext, component chasm.Component) error {

ghost Oct 10, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That's what I expect, that you can use the interface instead of a concrete type.

Base automatically changed from nexus-close-time to main October 16, 2025 21:23
@lina-temporal
lina-temporal enabled auto-merge (squash) October 16, 2025 21:33
@lina-temporal
lina-temporal merged commit 2234ce8 into main Oct 16, 2025
@lina-temporal
lina-temporal deleted the nexus-chasm branch October 16, 2025 21:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

Couldn't load reviewers.

Assignees

Couldn't load assignees.