go.temporal.io/server/chasm/registry.go
389 LOC · 213 covered · 176 uncovered · 94 ranges · 4478 concepts · 65 introducers · 1704 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 (
"errors"
"fmt"
"maps"
"reflect"
"regexp"
"strings"
"github.com/nexus-rpc/sdk-go/nexus"
"go.temporal.io/server/common/log"
"google.golang.org/grpc"
)
var (
// This is golang type identifier regex.
nameValidator = regexp.MustCompile(`^[A-Za-z_][A-Za-z0-9_]*$`)
)
type (
Registry struct {
libraries map[string]Library // library name -> library
// rc stands for RegistrableComponent.
rcByFqn map[string]*RegistrableComponent // fully qualified type name -> component
rcByID map[uint32]*RegistrableComponent // component type ID -> component
rcByGoType map[reflect.Type]*RegistrableComponent // component go type -> component
// rcContextValues is aggregated context values from all components,
// used for easy lookup when Context.Value(key) is called.
// Registration process will check for key conflicts and return error if same key is registered by multiple components.
rcContextValues map[any]valueWithFqn
// rt stands for RegistrableTask.
rtByFqn map[string]*RegistrableTask // fully qualified type name -> task
rtByID map[uint32]*RegistrableTask // task type ID -> task
rtByGoType map[reflect.Type]*RegistrableTask // task go type -> task
nexusServices map[string]*nexus.Service // service name -> nexus service
NexusEndpointProcessor *NexusEndpointProcessor
logger log.Logger
}
)
// valueWithFqn is a wrapper struct that associates a value with
// the fully qualified name (FQN) of the component that registered it.
type valueWithFqn struct {
v any
fqn string
}
return &Registry{
libraries: make(map[string]Library),
rcByFqn: make(map[string]*RegistrableComponent),
rcByID: make(map[uint32]*RegistrableComponent),
rcByGoType: make(map[reflect.Type]*RegistrableComponent),
rtByFqn: make(map[string]*RegistrableTask),
rtByID: make(map[uint32]*RegistrableTask),
rtByGoType: make(map[reflect.Type]*RegistrableTask),
rcContextValues: make(map[any]valueWithFqn),
nexusServices: make(map[string]*nexus.Service),
NexusEndpointProcessor: NewNexusEndpointProcessor(),
logger: logger,
}
}
if err := r.validateName(lib.Name()); err != nil {
}
return fmt.Errorf("library %s is already registered", lib.Name())
}
for _, c := range lib.Components() {
}
}
}
}
}
}
return err
}
}
}
// RegisterServices registers all gRPC services from all registered libraries.
for _, lib := range r.libraries {
lib.RegisterServices(server)
}
}
// ComponentFqnByID converts component type ID to fully qualified component type name.
// This method should only be used by CHASM framework internal code,
// NOT CHASM library developers.
rc, ok := r.rcByID[id]
if !ok {
}
}
// ComponentIDByFqn converts fully qualified component type name to component type ID.
// This method should only be used by CHASM framework internal code,
// NOT CHASM library developers.
func (r *Registry) ComponentIDByFqn(fqn string) (uint32, bool) {
rc, ok := r.rcByFqn[fqn]
if !ok {
return 0, false
}
return rc.componentID, true
}
// ComponentByID returns the registrable component for a given archetype ID.
// This method should only be used by CHASM framework internal code,
// NOT CHASM library developers.
rc, ok := r.rcByID[id]
return rc, ok
}
// ComponentIDFor converts registered component instance to component type ID.
// This method should only be used by CHASM framework internal code,
// NOT CHASM library developers.
rc, ok := r.componentFor(componentInstance)
if !ok {
return 0, false
}
}
// TaskByID returns the registrable task for a given task type ID.
// This method should only be used by CHASM framework internal code,
// NOT CHASM library developers.
rt, ok := r.rtByID[id]
return rt, ok
}
// TaskFqnByID converts task type ID to fully qualified task type name.
// This method should only be used by CHASM framework internal code,
// NOT CHASM library developers.
rt, ok := r.rtByID[id]
if !ok {
}
}
// TaskIDFor converts registered task instance to task type ID.
// This method should only be used by CHASM framework internal code,
// NOT CHASM library developers.
func (r *Registry) TaskIDFor(taskInstance any) (uint32, bool) {
visibility_queue_task_executor.go ×6
rt, ok := r.taskFor(taskInstance)
if !ok {
return 0, false
}
}
// ArchetypeDisplayName returns the human-readable name for a given archetype ID.
// This method should only be used by CHASM framework internal code,
// NOT CHASM library developers.
rc, ok := r.ComponentByID(id)
if !ok {
}
}
// ArchetypeIDOf returns the ArchetypeID for the given component Go type.
// This method should only be used by CHASM framework internal code,
// NOT CHASM library developers.
func (r *Registry) ArchetypeIDOf(componentGoType reflect.Type) (ArchetypeID, bool) {
registry.go ×1
rc, ok := r.rcByGoType[componentGoType]
if !ok {
}
}
rc, ok := r.rcByFqn[fqn]
return rc, ok
}
rt, ok := r.rtByFqn[fqn]
return rt, ok
}
func (r *Registry) componentFor(componentInstance any) (*RegistrableComponent, bool) {
registry.go ×1
rc, ok := r.rcByGoType[reflect.TypeOf(componentInstance)]
return rc, ok
}
rt, ok := r.rtByGoType[reflect.TypeOf(taskInstance)]
return rt, ok
}
func (r *Registry) componentOf(componentGoType reflect.Type) (*RegistrableComponent, bool) {
registry.go ×1
rc, ok := r.rcByGoType[componentGoType]
return rc, ok
}
rt, ok := r.rtByGoType[taskGoType]
return rt, ok
}
func (r *Registry) registerComponent(
lib namer,
rc *RegistrableComponent,
if err := r.validate(rc); err != nil {
}
if err != nil {
}
}
return fmt.Errorf("component %s maps to a reserved archetype id %d, please use a different name", fqn, UnspecifiedArchetypeID)
}
return fmt.Errorf("component ID %d collision between %s and %s", id, fqn, existingComponent.fqType())
}
return fmt.Errorf("context value key %v registered by component %s conflicts with component %s", key, fqn, existingValue.fqn)
}
v: value,
fqn: fqn,
}
}
// rc.goType implements Component interface; therefore, it must be a struct.
// This check to protect against the interface itself being registered.
(rc.goType.Kind() == reflect.Pointer && rc.goType.Elem().Kind() == reflect.Struct)) {
return fmt.Errorf("component type %s must be struct or pointer to struct", rc.goType.String())
registry.go ×1
}
return fmt.Errorf("component type %s is already registered", rc.goType.String())
registry.go ×1
}
r.rcByFqn[fqn] = rc
r.rcByID[id] = rc
r.rcByGoType[rc.goType] = rc
return nil
}
if err := r.validateName(rc.componentType); err != nil {
}
}
func (r *Registry) registerTask(
lib namer,
rt *RegistrableTask,
if err := r.validateName(rt.taskType); err != nil {
}
if err != nil {
}
}
return fmt.Errorf("task type ID %d collision between %s and %s", id, fqn, existingTask.fqType())
}
(rt.goType.Kind() == reflect.Pointer && rt.goType.Elem().Kind() == reflect.Struct)) {
return fmt.Errorf("task type %s must be struct or pointer to struct", rt.goType.String())
registry.go ×1
}
}
(rt.componentGoType.Kind() == reflect.Struct ||
(rt.componentGoType.Kind() == reflect.Pointer && rt.componentGoType.Elem().Kind() == reflect.Struct)) &&
rt.componentGoType.AssignableTo(reflect.TypeFor[Component]())) {
return fmt.Errorf("component type %s must be and interface or struct that implements Component interface", rt.componentGoType.String())
}
r.rtByID[id] = rt
r.rtByGoType[rt.goType] = rt
return nil
}
if n == "" {
}
return fmt.Errorf("name %s is invalid. name must follow golang identifier rules: %s", n, nameValidator.String())
registry.go ×1
}
}
func (r *Registry) validateVisibilityBusinessIDAlias(rc *RegistrableComponent) error {
registry.go ×2
if !hasVisibilityField(rc.goType) {
}
// Archetypes that contain a Field[*Visibility] must specify WithBusinessIDAlias.
return fmt.Errorf("component %s has Field[*Visibility] but no businessID alias; use WithBusinessIDAlias option", rc.componentType)
registrable_component.go ×1
}
}
var unmanagedFields []string
for f := range unmanagedFieldsOf(rc.goType) {
}
"Warning: CHASM component %s declares state fields that won't be managed by CHASM:\n\t%s",
fqn,
strings.Join(unmanagedFields, "\n\t")))
}
}
if _, ok := r.nexusServices[svc.Name]; ok {
}
return nil
}
// NexusServices returns all registered Nexus services.
// Return a copy to prevent external modification
services := make(map[string]*nexus.Service, len(r.nexusServices))
maps.Copy(services, r.nexusServices)
return services
}
if v, ok := r.rcContextValues[key]; ok {
}
}