go.temporal.io/server/common/namespace/namespace.go
377 LOC · 158 covered · 219 uncovered · 53 ranges · 16051 concepts · 44 introducers · 8111 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 namespace
import (
"fmt"
"maps"
"slices"
"time"
"github.com/google/uuid"
enumspb "go.temporal.io/api/enums/v1"
namespacepb "go.temporal.io/api/namespace/v1"
rulespb "go.temporal.io/api/rules/v1"
"go.temporal.io/api/serviceerror"
persistencespb "go.temporal.io/server/api/persistence/v1"
"go.temporal.io/server/common"
"go.temporal.io/server/common/util"
expmaps "golang.org/x/exp/maps"
)
type (
// Mutation changes a Namespace "in-flight" during a Clone operation.
Mutation interface {
apply(*Namespace)
}
// BadBinaryError is an error type carrying additional information about
// when/why/who configured a given checksum as being bad.
BadBinaryError struct {
cksum string
info *namespacepb.BadBinaryInfo
}
// ID is the unique identifier type for a Namespace.
ID string
// Name is a user-supplied nickname for a Namespace.
Name string
// Namespaces is a *Namespace slice
Namespaces []*Namespace
// Namespace contains the info and config for a namespace
Namespace struct {
info *persistencespb.NamespaceInfo
config *persistencespb.NamespaceConfig
configVersion int64
notificationVersion int64
customSearchAttributesMapper CustomSearchAttributesMapper
replicationResolver ReplicationResolver
}
CustomSearchAttributesMapper struct {
fieldToAlias map[string]string
aliasToField map[string]string
}
// ReplicationPolicy is the namespace's replication policy,
// derived from namespace's replication config
ReplicationPolicy int
)
const (
EmptyName Name = ""
EmptyID ID = ""
EmptyBusinessID = ""
// ReplicationPolicyOneCluster indicate that workflows does not need to be replicated
// applicable to local namespace & global namespace with one cluster
ReplicationPolicyOneCluster ReplicationPolicy = 0
// ReplicationPolicyMultiCluster indicate that workflows need to be replicated
ReplicationPolicyMultiCluster ReplicationPolicy = 1
)
return ID(uuid.NewString())
}
func FromPersistentState(
detail *persistencespb.NamespaceDetail,
resolver ReplicationResolver,
mutations ...Mutation,
if resolver == nil {
return nil, serviceerror.NewInvalidArgument("replicationResolver must be provided")
namespace.go ×1
}
info: detail.Info,
config: detail.Config,
configVersion: detail.ConfigVersion,
customSearchAttributesMapper: CustomSearchAttributesMapper{
fieldToAlias: detail.Config.CustomSearchAttributeAliases,
aliasToField: util.InverseMap(detail.Config.CustomSearchAttributeAliases),
},
replicationResolver: resolver,
}
for _, m := range mutations {
}
}
// Clone the resolver to get a deep copy of replication state
clonedResolver := ns.replicationResolver.Clone()
cloned := &Namespace{
info: common.CloneProto(ns.info),
config: common.CloneProto(ns.config),
configVersion: ns.configVersion,
customSearchAttributesMapper: CustomSearchAttributesMapper{
fieldToAlias: ns.customSearchAttributesMapper.fieldToAlias,
aliasToField: ns.customSearchAttributesMapper.aliasToField,
},
notificationVersion: ns.notificationVersion,
replicationResolver: clonedResolver,
}
for _, m := range mutations {
m.apply(cloned)
}
}
// VisibilityArchivalState observes the visibility archive configuration (state
// and URI) for this namespace.
return ArchivalConfigState{
State: ns.config.VisibilityArchivalState,
URI: ns.config.VisibilityArchivalUri,
}
}
// HistoryArchivalState observes the history archive configuration (state and
// URI) for this namespace.
return ArchivalConfigState{
State: ns.config.HistoryArchivalState,
URI: ns.config.HistoryArchivalUri,
}
}
// VerifyBinaryChecksum returns an error if the provided checksum is one of this
// namespace's configured bad binary checksums. The returned error (if any) will
// be unwrappable as BadBinaryError.
badBinMap := ns.config.GetBadBinaries().GetBinaries()
if badBinMap == nil {
}
}
}
// ID observes this namespace's permanent unique identifier in string form.
if ns.info == nil {
return ID("")
}
}
// Name observes this namespace's configured name.
if ns.info == nil {
}
}
if ns.info == nil {
return enumspb.NAMESPACE_STATE_UNSPECIFIED
}
}
func (ns *Namespace) ReplicationResolver() ReplicationResolver {
return ns.replicationResolver
}
func (ns *Namespace) ReplicationState(businessID string) enumspb.ReplicationState {
namespace.go ×1
return ns.replicationResolver.ReplicationState(businessID)
}
// ActiveClusterName observes the name of the cluster that is currently active
// for this namespace.
return ns.replicationResolver.ActiveClusterName(routingKey)
}
// ClusterNames observes the names of the clusters to which this namespace is
// replicated.
return ns.replicationResolver.ClusterNames(businessID)
}
// IsOnCluster returns true is namespace is registered on cluster otherwise false.
return slices.Contains(ns.ClusterNames(EmptyBusinessID), clusterName)
}
// ConfigVersion return the namespace config version
func (ns *Namespace) ConfigVersion() int64 {
return ns.configVersion
}
// FailoverVersion return the namespace failover version
return ns.replicationResolver.FailoverVersion(businessID)
}
// IsGlobalNamespace returns whether the namespace is a global namespace.
// Being a global namespace doesn't necessarily mean that there are multiple registered clusters for it, only that it
// has a failover version. To determine whether operations should be replicated for a namespace, see ReplicationPolicy.
return ns.replicationResolver.IsGlobalNamespace()
}
// FailoverNotificationVersion return the global notification version of when failover happened
func (ns *Namespace) FailoverNotificationVersion() int64 {
return ns.replicationResolver.FailoverNotificationVersion()
}
// Info returns the underlying NamespaceInfo proto. The returned value is the registry's own
// copy and must not be mutated.
return ns.info
}
// Config returns the underlying NamespaceConfig proto. The returned value is the registry's own
// copy and must not be mutated.
return ns.config
}
// ReplicationConfig returns the underlying NamespaceReplicationConfig proto. The returned value
// is the registry's own copy and must not be mutated.
func (ns *Namespace) ReplicationConfig() *persistencespb.NamespaceReplicationConfig {
namespace.go ×3
return ns.replicationResolver.ReplicationConfig()
}
// NotificationVersion return the global notification version of when namespace changed
return ns.notificationVersion
}
// ActiveInCluster returns whether the namespace is active in the given cluster.
// A namespace is considered active if it is either a local namespace or a global
// namespace whose active cluster matches the provided cluster.
// Note: Do not use this to determine if a workflow is active in the cluster.
// Use ActiveClusterName(businessID) instead.
return ns.replicationResolver.ActiveInCluster(clusterName)
}
// ReplicationPolicy return the derived workflow replication policy
// frontend guarantee that the clusters always contains the active
// namespace, so if the # of clusters is 1 then we do not need to send out
// any events for replication
if ns.replicationResolver.IsGlobalNamespace() && len(ns.ClusterNames(EmptyBusinessID)) > 1 {
}
}
// GetReplicationResolver return the replication resolover
func (ns *Namespace) GetReplicationResolver() ReplicationResolver {
return ns.replicationResolver
}
if ns.info.Data == nil {
return ""
}
}
// Retention returns retention duration for this namespace.
if ns.config.Retention == nil {
}
}
// CustomSearchAttributesMapper is a part of temporary solution. Do not use this method.
func (ns *Namespace) CustomSearchAttributesMapper() CustomSearchAttributesMapper {
handler.go ×25
return ns.customSearchAttributesMapper
}
if ns.config.WorkflowRules == nil {
return nil
}
return expmaps.Values(ns.config.WorkflowRules)
}
func (ns *Namespace) GetWorkflowRule(ruleID string) (*rulespb.WorkflowRule, bool) {
if ns.config.WorkflowRules == nil {
return nil, false
}
result, ok := ns.config.WorkflowRules[ruleID]
return result, ok
}
// Error returns the reason associated with this bad binary.
func (e BadBinaryError) Error() string {
return e.info.Reason
}
// Reason returns the reason associated with this bad binary.
func (e BadBinaryError) Reason() string {
return e.info.Reason
}
// Operator returns the operator associated with this bad binary.
func (e BadBinaryError) Operator() string {
return e.info.Operator
}
// Created returns the time at which this bad binary was declared to be bad.
func (e BadBinaryError) Created() time.Time {
return e.info.CreateTime.AsTime()
}
// Checksum observes the binary checksum that caused this error.
func (e BadBinaryError) Checksum() string {
return e.cksum
}
return string(id)
}
return id == EmptyID
}
return string(n)
}
return n == EmptyName
}
func (m *CustomSearchAttributesMapper) GetAlias(fieldName string, namespace string) (string, error) {
namespace.go ×1
alias, ok := m.fieldToAlias[fieldName]
if !ok {
fmt.Sprintf("Namespace %s has no mapping defined for field name %s", namespace, fieldName),
)
}
}
func (m *CustomSearchAttributesMapper) GetFieldName(alias string, namespace string) (string, error) {
namespace.go ×1
fieldName, ok := m.aliasToField[alias]
if !ok {
fmt.Sprintf("Namespace %s has no mapping defined for search attribute %s", namespace, alias),
)
}
}
func (m *CustomSearchAttributesMapper) FieldToAliasMap() map[string]string {
return maps.Clone(m.fieldToAlias)
}