mirror of
https://github.com/temporalio/temporal.git
synced 2026-08-30 18:41:49 -07:00
## What changed? - Replaced custom search attribute aliases with standard ones: - ActivityStatus → ExecutionStatus (using the standard execution status field) - ActivityTaskQueue → TaskQueue (using the standard task queue field) - ActivityType now uses the alias name directly instead of a constant - Renamed the GetValue() function to SearchAttributeValue() for better clarity - Changed Activity.Store field type from chasm.Field[ActivityStore] to chasm.ParentPtr[ActivityStore] to avoid the storage overhead of a pointer that is only ever expected to be a parent - Fixed error types in handler.go: changed from serviceerror.NewFailedPrecondition to serviceerror.NewInvalidArgumentf for invalid policy errors - Improved ParentPtr.TryGet() to gracefully return false instead of panicking when not initialized
103 lines
3.1 KiB
Go
103 lines
3.1 KiB
Go
package chasm
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
|
|
"go.temporal.io/api/serviceerror"
|
|
"go.temporal.io/server/common/softassert"
|
|
)
|
|
|
|
const (
|
|
parentPtrInternalFieldName = "Internal"
|
|
)
|
|
|
|
// ParentPtr is a in-memory pointer to the parent component of a CHASM component.
|
|
//
|
|
// CHASM map is not a component, so if a component is inside a map, its ParentPtr
|
|
// will point to the nearest ancestor component that is not a map.
|
|
//
|
|
// ParentPtr is only initialized and available for use **after** the transition that
|
|
// creates the component using ParentPtr is completed.
|
|
type ParentPtr[T any] struct {
|
|
// Exporting this field as this generic struct needs to be created via reflection,
|
|
// and reflection can't set private fields.
|
|
Internal parentPtrInternal
|
|
}
|
|
|
|
type parentPtrInternal struct {
|
|
// Storing currentNode instead of parent component Node here so that
|
|
// we can differentiate between root node and non-initialized ParentPtr.
|
|
currentNode *Node
|
|
}
|
|
|
|
// Get returns the parent component, deserializing it if necessary.
|
|
// Panics rather than returning an error, as errors are supposed to be handled by the framework as opposed to the
|
|
// application.
|
|
func (p ParentPtr[T]) Get(chasmContext Context) T {
|
|
vT, ok := p.TryGet(chasmContext)
|
|
if !ok {
|
|
// nolint:forbidigo // Panic is intended here for framework error handling.
|
|
panic(serviceerror.NewInternal("expect parent component value but got nil"))
|
|
}
|
|
return vT
|
|
}
|
|
|
|
// TryGet returns the parent component and a boolean indicating if the value was found,
|
|
// deserializing if necessary.
|
|
// Panics rather than returning an error, as errors are supposed to be handled by the framework as opposed to the
|
|
// application.
|
|
func (p ParentPtr[T]) TryGet(chasmContext Context) (T, bool) {
|
|
var nilT T
|
|
if p.Internal.currentNode == nil {
|
|
// ParentPtr not initialized
|
|
return nilT, false
|
|
}
|
|
|
|
parent := p.Internal.currentNode.parent
|
|
if parent == nil {
|
|
return nilT, false
|
|
}
|
|
|
|
for parent.isMap() {
|
|
parent = parent.parent
|
|
if parent == nil {
|
|
encodedPath, _ := p.Internal.currentNode.getEncodedPath()
|
|
// nolint:forbidigo // Panic is intended here for framework error handling.
|
|
panic(softassert.UnexpectedInternalErr(
|
|
p.Internal.currentNode.logger,
|
|
"unable to find parent component for CHASM component inside a map",
|
|
fmt.Errorf("child node name: %s", encodedPath),
|
|
))
|
|
}
|
|
}
|
|
|
|
if !parent.isComponent() {
|
|
// nolint:forbidigo // Panic is intended here for framework error handling.
|
|
panic(softassert.UnexpectedInternalErr(
|
|
parent.logger,
|
|
"unexpected CHASM node that has a child component",
|
|
fmt.Errorf("node %s, node metadata: %s",
|
|
parent.nodeName,
|
|
parent.serializedNode.GetMetadata().String(),
|
|
),
|
|
))
|
|
}
|
|
|
|
if err := parent.prepareComponentValue(chasmContext); err != nil {
|
|
// nolint:forbidigo // Panic is intended here for framework error handling.
|
|
panic(err)
|
|
}
|
|
|
|
if parent.value == nil {
|
|
return nilT, false
|
|
}
|
|
|
|
vT, isT := parent.value.(T)
|
|
if !isT {
|
|
// nolint:forbidigo // Panic is intended here for framework error handling.
|
|
panic(serviceerror.NewInternalf("parent component value doesn't implement %s", reflect.TypeFor[T]().Name()))
|
|
}
|
|
return vT, true
|
|
}
|