go.temporal.io/server/chasm/ref.go
187 LOC · 82 covered · 105 uncovered · 20 ranges · 308 concepts · 14 introducers · 128 tests
File neighbourhood
The centred file is linked to every concept that introduces one of its ranges, every test that runs code from the file, and the gray connector concepts standing between those tests and the file's own introducer concepts. Undirected links join concepts to every file where they introduce source and concepts to the tests they introduce; arrows show specialization between the displayed concepts and bridge only concepts omitted from this view. Concept colors match the source ranges below; connector concepts have no source color and are shown in gray.
Focused file, its introducer and connector concepts, their introduced files, and tests that run code from the file
In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the related-file, concept, and source links on this page.
Graph controls are ready.
Interactive rendering requires JavaScript and WebGL. Use the related-file, concept, and source links on this page while the interactive map is unavailable.
package chasm
import (
"reflect"
"go.temporal.io/api/serviceerror"
persistencespb "go.temporal.io/server/api/persistence/v1"
)
// ErrMalformedComponentRef is returned when component ref bytes cannot be deserialized.
var ErrMalformedComponentRef = serviceerror.NewInvalidArgument("malformed component ref")
// ErrInvalidComponentRef is returned when component ref bytes deserialize to an invalid component ref.
var ErrInvalidComponentRef = serviceerror.NewInvalidArgument("invalid component ref")
// ExecutionKey uniquely identifies a CHASM execution in the system.
type ExecutionKey struct {
NamespaceID string
BusinessID string
RunID string
}
type ComponentRef struct {
ExecutionKey
// archetypeID is CHASM framework's internal ID for the type of the root component of the CHASM execution.
//
// It is used to find and validate the loaded execution has the right archetype, especially when runID
// is not specified in the ExecutionKey.
archetypeID ArchetypeID
// executionGoType is used for determining the ComponetRef's archetype.
// When CHASM deverloper needs to create a ComponentRef, they will only provide the component type,
// and leave the work of determining archetypeID to the CHASM framework.
executionGoType reflect.Type
// executionLastUpdateVT is the consistency token for the entire execution.
executionLastUpdateVT *persistencespb.VersionedTransition
// componentType is the fully qualified component type name.
// It is for performing partial loading more efficiently in future versions of CHASM.
//
// From the componentType, we can find the registered component struct definition,
// then use reflection to find sub-components and understand if those sub-components
// need to be loaded or not.
// We only need to do this for sub-components, path for parent/ancenstor components
// can be inferred from the current component path and they always needs to be loaded.
//
// componentType string
// componentPath and componentInitialVT are used to identify a component.
componentPath []string
componentInitialVT *persistencespb.VersionedTransition
validationFn func(NodeBackend, Context, Component, *Registry) error
}
// NewComponentRef creates a new ComponentRef with a registered root component go type.
//
// In V1, if you don't have a ref,
// then you can only interact with the (top level) execution.
func NewComponentRef[C Component](
executionKey ExecutionKey,
return ComponentRef{
ExecutionKey: executionKey,
executionGoType: reflect.TypeFor[C](),
}
}
// NewComponentRefByArchetypeID creates a new ComponentRef with a known archetype ID.
// This should only be used by CHASM framework internals.
// CHASM library developers should use [NewComponentRef] instead.
func NewComponentRefByArchetypeID(
executionKey ExecutionKey,
archetypeID ArchetypeID,
return ComponentRef{
ExecutionKey: executionKey,
archetypeID: archetypeID,
}
}
// forConsistencyLevel returns a copy of the ref adjusted for the requested [RefConsistencyLevel] by
// dropping the consistency tokens (and, at the weakest level, the run ID) that the level does not enforce.
// See [RefConsistencyLevel] for the ladder.
func (r *ComponentRef) forConsistencyLevel(level RefConsistencyLevel) (ComponentRef, error) {
ref.go ×1
ref := *r
switch level {
// Strongest (default): enforce the execution-level token; nothing relaxed.
return ref, nil
// Tolerate a stale execution transition without losing the staleness guarantee: run the
// execution staleness check ([Node.IsStale]) against the component's creation transition
// instead of the execution's last update. This still reloads a mutable state that predates
// the component (so the handler never operates on a state that doesn't yet know about the
// component), while no longer requiring the ref to match the latest execution transition.
// The creation transition is also matched in [Node.Component]; identity is otherwise the
// caller's responsibility (e.g. request ID).
ref.executionLastUpdateVT = ref.componentInitialVT
return ref, nil
// Weakest: resolve by component path on the current run. Drop the run ID and every versioned
// transition; identity must be re-established by caller logic (e.g. request ID).
ref.executionLastUpdateVT = nil
ref.componentInitialVT = nil
ref.RunID = ""
return ref, nil
default:
return ref, serviceerror.NewInternalf("unknown ref consistency level: %d", level)
}
}
func (r *ComponentRef) ArchetypeID(
registry *Registry,
if r.archetypeID != UnspecifiedArchetypeID {
}
if !ok {
return 0, serviceerror.NewInternal("unknown chasm component type: " + r.executionGoType.String())
}
return r.archetypeID, nil
}
func (r *ComponentRef) Serialize(
registry *Registry,
if r == nil {
return nil, nil
}
if err != nil {
return nil, err
}
NamespaceId: r.NamespaceID,
BusinessId: r.BusinessID,
RunId: r.RunID,
ArchetypeId: archetypeID,
ExecutionVersionedTransition: r.executionLastUpdateVT,
ComponentPath: r.componentPath,
ComponentInitialVersionedTransition: r.componentInitialVT,
}
return pRef.Marshal()
}
// DeserializeComponentRef deserializes a byte slice into a ComponentRef.
// Provides caller the access to information including ExecutionKey, Archetype, and ShardingKey.
if len(data) == 0 {
}
if err := pRef.Unmarshal(data); err != nil {
}
if ref.BusinessID == "" || ref.NamespaceID == "" {
return ComponentRef{}, ErrInvalidComponentRef
}
}
// ProtoRefToComponentRef converts a persistence ChasmComponentRef reference to a
// ComponentRef. This is useful for situations where the protobuf ComponentRef has
// already been deserialized as part of an enclosing message.
return ComponentRef{
ExecutionKey: ExecutionKey{
NamespaceID: pRef.NamespaceId,
BusinessID: pRef.BusinessId,
RunID: pRef.RunId,
},
archetypeID: pRef.ArchetypeId,
executionLastUpdateVT: pRef.ExecutionVersionedTransition,
componentPath: pRef.ComponentPath,
componentInitialVT: pRef.ComponentInitialVersionedTransition,
}
}