Skip to content

CHASM: Sync structure after every pure task#8903

Merged
yycptt merged 7 commits into
temporalio:mainfrom
yycptt:chasm-pure-task-sync-structure
Jan 6, 2026
Merged

CHASM: Sync structure after every pure task#8903
yycptt merged 7 commits into
temporalio:mainfrom
yycptt:chasm-pure-task-sync-structure

Conversation

@yycptt
Copy link
Copy Markdown
Member

@yycptt yycptt commented Dec 27, 2025

What changed?

  • Maintain a map from component & data value to their chasm tree Node
  • Sync tree structure after processing every pure task

Why?

  • CHASM: Sync tree structure when processing pure tasks #8400 fixed the bug where a pure task deletes another node with pure tasks. However, a node can also have multiple pure tasks and a pure task can delete the node itself via a pointer, in this case remaining pure tasks should not be executed. To fix that, we will need to perform tree structure sync after every pure task processing and be able to tell after syncing if a node/component still exists or not.

  • With the value -> Node map we can easily tell if a component still exists or not. It can also simplify some existing implementations where we scan the entire tree to find the node for a Component: e.g. Ref(), component/DataValuePath().

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)

@yycptt yycptt requested a review from lina-temporal December 27, 2025 00:10
@yycptt yycptt marked this pull request as ready for review December 31, 2025 23:05
@yycptt yycptt requested review from a team as code owners December 31, 2025 23:05
Comment thread chasm/tree.go Outdated
Comment thread chasm/tree.go
Comment on lines +2528 to +2529
// Node get deleted when previous pure tasks of the same component are executed.
// e.g. via a (parent) pointer.
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 don't quite follow here how this involves the parent pointer, wouldn't the node only be deleted if some pure task deleted the node's component?

Copy link
Copy Markdown
Member Author

@yycptt yycptt Jan 6, 2026

Choose a reason for hiding this comment

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

Without a pointer, I don't think a task executor is able to delete the node itself.

The task executor is given the Component and we don't have any api to delete a component just by it's value (that will be something like chasmContext.Remove(component) probably).
The only way I am aware of for removing a component is parentComponent.Component = NewEmptyField() which needs a parent pointer, or a pointer to an ancestor node

Comment thread chasm/tree_test.go Outdated
@yycptt yycptt force-pushed the chasm-pure-task-sync-structure branch from fa35df9 to 0916999 Compare January 6, 2026 01:21
Comment thread chasm/tree.go
// Processed task should become invalid and will be removed upon CloseTransaction().

// TODO: Add a validation for that and return an internal error if tasks is still valid after processing.
// Alternatively, remove task from PureTasks slice after processing, but that requires persisting the
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I realized that I can't simply remove thing from PureTasks here since the change may not be persisted. I've reverted that for now.

Comment thread chasm/tree.go
return err
}

cleanedUp, err := node.closeTransactionCleanupInvalidTasks(taskValidationContext)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Since we are not removing invalid tasks in EachPureTask(), I think this change is necessary (though technically this can be done in a separate PR but included here as I am fixing pure task processing anyway).

Basically we need to perform task validation for all tasks in the tree to make sure persisted tasks are always valid.

Here's what can happen if we have a invalid persisted task:
Say at T = 0 we have a component C, which has a pure task T with the smallest scheduled timestamp across the tree. A physical pure task is generated for it, and it's taskStatus is set to created.
Later at T = 1, some other node get updated (e.g. its parent P), and somehow invalidated the pure task (e.g. due to access rule). Without the change here, since C is not updated, the pure task T won't be deleted when P is updated.
At T = 2, the physical pure task for T is executed, it sees T is invalid, so doesn't do anything. Now as long as C is not updated, the T with taskStatus = create will always be there. Also it's T has the smallest timestamp, it will prevent any new physical pure task from being generated. Refresh task also doesn't help much here as the invalid T is still there.

With this change the pure task will be deleted at T = 1.

@yycptt
Copy link
Copy Markdown
Member Author

yycptt commented Jan 6, 2026

I will go ahead and land this first to catch the release. Let me know if there's any comments and I will address them in follow up PRs.

@yycptt yycptt merged commit 7fe39fc into temporalio:main Jan 6, 2026
135 of 140 checks passed
@yycptt yycptt deleted the chasm-pure-task-sync-structure branch January 6, 2026 08:14
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