go.temporal.io/server@v1.23.0/common/archiver/archival_metadata.go (about) 1 // The MIT License 2 // 3 // Copyright (c) 2020 Temporal Technologies Inc. All rights reserved. 4 // 5 // Copyright (c) 2020 Uber Technologies, Inc. 6 // 7 // Permission is hereby granted, free of charge, to any person obtaining a copy 8 // of this software and associated documentation files (the "Software"), to deal 9 // in the Software without restriction, including without limitation the rights 10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 // copies of the Software, and to permit persons to whom the Software is 12 // furnished to do so, subject to the following conditions: 13 // 14 // The above copyright notice and this permission notice shall be included in 15 // all copies or substantial portions of the Software. 16 // 17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 // THE SOFTWARE. 24 25 //go:generate mockgen -copyright_file ../../LICENSE -package $GOPACKAGE -source $GOFILE -destination archival_metadata_mock.go 26 27 package archiver 28 29 import ( 30 "fmt" 31 "strings" 32 33 enumspb "go.temporal.io/api/enums/v1" 34 35 "go.temporal.io/server/common/config" 36 37 "go.temporal.io/server/common/dynamicconfig" 38 ) 39 40 type ( 41 // ArchivalMetadata provides cluster level archival information 42 ArchivalMetadata interface { 43 GetHistoryConfig() ArchivalConfig 44 GetVisibilityConfig() ArchivalConfig 45 } 46 47 // ArchivalConfig is an immutable representation of the archival configuration of the cluster 48 // This config is determined at cluster startup time 49 ArchivalConfig interface { 50 ClusterConfiguredForArchival() bool 51 GetClusterState() ArchivalState 52 ReadEnabled() bool 53 GetNamespaceDefaultState() enumspb.ArchivalState 54 GetNamespaceDefaultURI() string 55 StaticClusterState() ArchivalState 56 } 57 58 archivalMetadata struct { 59 historyConfig ArchivalConfig 60 visibilityConfig ArchivalConfig 61 } 62 63 archivalConfig struct { 64 staticClusterState ArchivalState 65 dynamicClusterState dynamicconfig.StringPropertyFn 66 enableRead dynamicconfig.BoolPropertyFn 67 namespaceDefaultState enumspb.ArchivalState 68 namespaceDefaultURI string 69 } 70 71 // ArchivalState represents the archival state of the cluster 72 ArchivalState int 73 ) 74 75 func (a *archivalConfig) StaticClusterState() ArchivalState { 76 return a.staticClusterState 77 } 78 79 const ( 80 // ArchivalDisabled means this cluster is not configured to handle archival 81 ArchivalDisabled ArchivalState = iota 82 // ArchivalPaused means this cluster is configured to handle archival but is currently not archiving 83 // This state is not yet implemented, as of now ArchivalPaused is treated the same way as ArchivalDisabled 84 ArchivalPaused 85 // ArchivalEnabled means this cluster is currently archiving 86 ArchivalEnabled 87 ) 88 89 // NewArchivalMetadata constructs a new ArchivalMetadata 90 func NewArchivalMetadata( 91 dc *dynamicconfig.Collection, 92 historyState string, 93 historyReadEnabled bool, 94 visibilityState string, 95 visibilityReadEnabled bool, 96 namespaceDefaults *config.ArchivalNamespaceDefaults, 97 ) ArchivalMetadata { 98 historyConfig := NewArchivalConfig( 99 historyState, 100 dc.GetStringProperty(dynamicconfig.HistoryArchivalState, historyState), 101 dc.GetBoolProperty(dynamicconfig.EnableReadFromHistoryArchival, historyReadEnabled), 102 namespaceDefaults.History.State, 103 namespaceDefaults.History.URI, 104 ) 105 106 visibilityConfig := NewArchivalConfig( 107 visibilityState, 108 dc.GetStringProperty(dynamicconfig.VisibilityArchivalState, visibilityState), 109 dc.GetBoolProperty(dynamicconfig.EnableReadFromVisibilityArchival, visibilityReadEnabled), 110 namespaceDefaults.Visibility.State, 111 namespaceDefaults.Visibility.URI, 112 ) 113 114 return &archivalMetadata{ 115 historyConfig: historyConfig, 116 visibilityConfig: visibilityConfig, 117 } 118 } 119 120 func (metadata *archivalMetadata) GetHistoryConfig() ArchivalConfig { 121 return metadata.historyConfig 122 } 123 124 func (metadata *archivalMetadata) GetVisibilityConfig() ArchivalConfig { 125 return metadata.visibilityConfig 126 } 127 128 // NewArchivalConfig constructs a new valid ArchivalConfig 129 func NewArchivalConfig( 130 staticClusterStateStr string, 131 dynamicClusterState dynamicconfig.StringPropertyFn, 132 enableRead dynamicconfig.BoolPropertyFn, 133 namespaceDefaultStateStr string, 134 namespaceDefaultURI string, 135 ) ArchivalConfig { 136 staticClusterState, err := getClusterArchivalState(staticClusterStateStr) 137 if err != nil { 138 panic(err) 139 } 140 namespaceDefaultState, err := getNamespaceArchivalState(namespaceDefaultStateStr) 141 if err != nil { 142 panic(err) 143 } 144 145 return &archivalConfig{ 146 staticClusterState: staticClusterState, 147 dynamicClusterState: dynamicClusterState, 148 enableRead: enableRead, 149 namespaceDefaultState: namespaceDefaultState, 150 namespaceDefaultURI: namespaceDefaultURI, 151 } 152 } 153 154 // NewDisabledArchvialConfig returns an ArchivalConfig where archival is disabled for both the cluster and the namespace 155 func NewDisabledArchvialConfig() ArchivalConfig { 156 return &archivalConfig{ 157 staticClusterState: ArchivalDisabled, 158 dynamicClusterState: nil, 159 enableRead: nil, 160 namespaceDefaultState: enumspb.ARCHIVAL_STATE_DISABLED, 161 namespaceDefaultURI: "", 162 } 163 } 164 165 // NewEnabledArchivalConfig returns an ArchivalConfig where archival is enabled for both the cluster and the namespace 166 func NewEnabledArchivalConfig() ArchivalConfig { 167 return &archivalConfig{ 168 staticClusterState: ArchivalEnabled, 169 dynamicClusterState: dynamicconfig.GetStringPropertyFn("enabled"), 170 enableRead: dynamicconfig.GetBoolPropertyFn(true), 171 namespaceDefaultState: enumspb.ARCHIVAL_STATE_ENABLED, 172 namespaceDefaultURI: "some-uri", 173 } 174 } 175 176 // ClusterConfiguredForArchival returns true if cluster is configured to handle archival, false otherwise 177 func (a *archivalConfig) ClusterConfiguredForArchival() bool { 178 return a.GetClusterState() == ArchivalEnabled 179 } 180 181 func (a *archivalConfig) GetClusterState() ArchivalState { 182 // Only check dynamic config when archival is enabled in static config. 183 // If archival is disabled in static config, there will be no provider section in the static config 184 // and the archiver provider can not create any archiver. Therefore, in that case, 185 // even dynamic config says archival is enabled, we should ignore that. 186 // Only when archival is enabled in static config, should we check if there's any difference between static config and dynamic config. 187 if a.staticClusterState != ArchivalEnabled { 188 return a.staticClusterState 189 } 190 191 dynamicStateStr := a.dynamicClusterState() 192 dynamicState, err := getClusterArchivalState(dynamicStateStr) 193 if err != nil { 194 return ArchivalDisabled 195 } 196 return dynamicState 197 } 198 199 func (a *archivalConfig) ReadEnabled() bool { 200 if !a.ClusterConfiguredForArchival() { 201 return false 202 } 203 return a.enableRead() 204 } 205 206 func (a *archivalConfig) GetNamespaceDefaultState() enumspb.ArchivalState { 207 return a.namespaceDefaultState 208 } 209 210 func (a *archivalConfig) GetNamespaceDefaultURI() string { 211 return a.namespaceDefaultURI 212 } 213 214 func getClusterArchivalState(str string) (ArchivalState, error) { 215 str = strings.TrimSpace(strings.ToLower(str)) 216 switch str { 217 case "", config.ArchivalDisabled: 218 return ArchivalDisabled, nil 219 case config.ArchivalPaused: 220 return ArchivalPaused, nil 221 case config.ArchivalEnabled: 222 return ArchivalEnabled, nil 223 } 224 return ArchivalDisabled, fmt.Errorf("invalid archival state of %v for cluster, valid states are: {\"\", \"disabled\", \"paused\", \"enabled\"}", str) 225 } 226 227 func getNamespaceArchivalState(str string) (enumspb.ArchivalState, error) { 228 str = strings.TrimSpace(strings.ToLower(str)) 229 switch str { 230 case "", config.ArchivalDisabled: 231 return enumspb.ARCHIVAL_STATE_DISABLED, nil 232 case config.ArchivalEnabled: 233 return enumspb.ARCHIVAL_STATE_ENABLED, nil 234 } 235 return enumspb.ARCHIVAL_STATE_DISABLED, fmt.Errorf("invalid archival state of %v for namespace, valid states are: {\"\", \"disabled\", \"enabled\"}", str) 236 }