go.temporal.io/server@v1.23.0/common/persistence/visibility/factory.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 package visibility 26 27 import ( 28 "go.temporal.io/server/common/config" 29 "go.temporal.io/server/common/dynamicconfig" 30 "go.temporal.io/server/common/log" 31 "go.temporal.io/server/common/log/tag" 32 "go.temporal.io/server/common/metrics" 33 "go.temporal.io/server/common/persistence/sql/sqlplugin/mysql" 34 "go.temporal.io/server/common/persistence/sql/sqlplugin/postgresql" 35 "go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite" 36 "go.temporal.io/server/common/persistence/visibility/manager" 37 "go.temporal.io/server/common/persistence/visibility/store" 38 "go.temporal.io/server/common/persistence/visibility/store/elasticsearch" 39 esclient "go.temporal.io/server/common/persistence/visibility/store/elasticsearch/client" 40 "go.temporal.io/server/common/persistence/visibility/store/sql" 41 "go.temporal.io/server/common/persistence/visibility/store/standard" 42 "go.temporal.io/server/common/persistence/visibility/store/standard/cassandra" 43 standardSql "go.temporal.io/server/common/persistence/visibility/store/standard/sql" 44 "go.temporal.io/server/common/resolver" 45 "go.temporal.io/server/common/searchattribute" 46 ) 47 48 type VisibilityStoreFactory interface { 49 NewVisibilityStore( 50 cfg config.CustomDatastoreConfig, 51 r resolver.ServiceResolver, 52 logger log.Logger, 53 metricsHandler metrics.Handler, 54 ) (store.VisibilityStore, error) 55 } 56 57 func NewManager( 58 persistenceCfg config.Persistence, 59 persistenceResolver resolver.ServiceResolver, 60 customVisibilityStoreFactory VisibilityStoreFactory, 61 62 esClient esclient.Client, 63 esProcessorConfig *elasticsearch.ProcessorConfig, 64 searchAttributesProvider searchattribute.Provider, 65 searchAttributesMapperProvider searchattribute.MapperProvider, 66 67 maxReadQPS dynamicconfig.IntPropertyFn, 68 maxWriteQPS dynamicconfig.IntPropertyFn, 69 operatorRPSRatio dynamicconfig.FloatPropertyFn, 70 enableReadFromSecondaryVisibility dynamicconfig.BoolPropertyFnWithNamespaceFilter, 71 secondaryVisibilityWritingMode dynamicconfig.StringPropertyFn, 72 visibilityDisableOrderByClause dynamicconfig.BoolPropertyFnWithNamespaceFilter, 73 visibilityEnableManualPagination dynamicconfig.BoolPropertyFnWithNamespaceFilter, 74 75 metricsHandler metrics.Handler, 76 logger log.Logger, 77 ) (manager.VisibilityManager, error) { 78 visibilityManager, err := newVisibilityManagerFromDataStoreConfig( 79 persistenceCfg.GetVisibilityStoreConfig(), 80 persistenceResolver, 81 customVisibilityStoreFactory, 82 esClient, 83 esProcessorConfig, 84 searchAttributesProvider, 85 searchAttributesMapperProvider, 86 maxReadQPS, 87 maxWriteQPS, 88 operatorRPSRatio, 89 visibilityDisableOrderByClause, 90 visibilityEnableManualPagination, 91 metricsHandler, 92 logger, 93 ) 94 if err != nil { 95 return nil, err 96 } 97 if visibilityManager == nil { 98 logger.Fatal("invalid config: visibility store must be configured") 99 return nil, nil 100 } 101 102 secondaryVisibilityManager, err := newVisibilityManagerFromDataStoreConfig( 103 persistenceCfg.GetSecondaryVisibilityStoreConfig(), 104 persistenceResolver, 105 customVisibilityStoreFactory, 106 esClient, 107 esProcessorConfig, 108 searchAttributesProvider, 109 searchAttributesMapperProvider, 110 maxReadQPS, 111 maxWriteQPS, 112 operatorRPSRatio, 113 visibilityDisableOrderByClause, 114 visibilityEnableManualPagination, 115 metricsHandler, 116 logger, 117 ) 118 if err != nil { 119 return nil, err 120 } 121 122 if secondaryVisibilityManager != nil { 123 isPrimaryAdvancedSQL := false 124 isSecondaryAdvancedSQL := false 125 switch visibilityManager.GetStoreNames()[0] { 126 case mysql.PluginNameV8, postgresql.PluginNameV12, postgresql.PluginNameV12PGX, sqlite.PluginName: 127 isPrimaryAdvancedSQL = true 128 } 129 switch secondaryVisibilityManager.GetStoreNames()[0] { 130 case mysql.PluginNameV8, postgresql.PluginNameV12, postgresql.PluginNameV12PGX, sqlite.PluginName: 131 isSecondaryAdvancedSQL = true 132 } 133 if isPrimaryAdvancedSQL && !isSecondaryAdvancedSQL { 134 logger.Fatal("invalid config: dual visibility combination not supported") 135 return nil, nil 136 } 137 138 managerSelector := newDefaultManagerSelector( 139 visibilityManager, 140 secondaryVisibilityManager, 141 enableReadFromSecondaryVisibility, 142 secondaryVisibilityWritingMode, 143 ) 144 return NewVisibilityManagerDual( 145 visibilityManager, 146 secondaryVisibilityManager, 147 managerSelector, 148 ), nil 149 } 150 151 return visibilityManager, nil 152 } 153 154 func newVisibilityManager( 155 visStore store.VisibilityStore, 156 maxReadQPS dynamicconfig.IntPropertyFn, 157 maxWriteQPS dynamicconfig.IntPropertyFn, 158 operatorRPSRatio dynamicconfig.FloatPropertyFn, 159 metricsHandler metrics.Handler, 160 visibilityPluginNameTag metrics.Tag, 161 logger log.Logger, 162 ) manager.VisibilityManager { 163 if visStore == nil { 164 return nil 165 } 166 logger.Info( 167 "creating new visibility manager", 168 tag.NewStringTag(visibilityPluginNameTag.Key(), visibilityPluginNameTag.Value()), 169 tag.NewStringTag("visibility_index_name", visStore.GetIndexName()), 170 ) 171 var visManager manager.VisibilityManager = newVisibilityManagerImpl(visStore, logger) 172 173 // wrap with rate limiter 174 visManager = NewVisibilityManagerRateLimited( 175 visManager, 176 maxReadQPS, 177 maxWriteQPS, 178 operatorRPSRatio, 179 ) 180 // wrap with metrics client 181 visManager = NewVisibilityManagerMetrics( 182 visManager, 183 metricsHandler, 184 logger, 185 visibilityPluginNameTag, 186 ) 187 return visManager 188 } 189 190 //nolint:revive // too many arguments 191 func newVisibilityManagerFromDataStoreConfig( 192 dsConfig config.DataStore, 193 persistenceResolver resolver.ServiceResolver, 194 customVisibilityStoreFactory VisibilityStoreFactory, 195 196 esClient esclient.Client, 197 esProcessorConfig *elasticsearch.ProcessorConfig, 198 searchAttributesProvider searchattribute.Provider, 199 searchAttributesMapperProvider searchattribute.MapperProvider, 200 201 maxReadQPS dynamicconfig.IntPropertyFn, 202 maxWriteQPS dynamicconfig.IntPropertyFn, 203 operatorRPSRatio dynamicconfig.FloatPropertyFn, 204 visibilityDisableOrderByClause dynamicconfig.BoolPropertyFnWithNamespaceFilter, 205 visibilityEnableManualPagination dynamicconfig.BoolPropertyFnWithNamespaceFilter, 206 207 metricsHandler metrics.Handler, 208 logger log.Logger, 209 ) (manager.VisibilityManager, error) { 210 visStore, err := newVisibilityStoreFromDataStoreConfig( 211 dsConfig, 212 persistenceResolver, 213 customVisibilityStoreFactory, 214 esClient, 215 esProcessorConfig, 216 searchAttributesProvider, 217 searchAttributesMapperProvider, 218 visibilityDisableOrderByClause, 219 visibilityEnableManualPagination, 220 metricsHandler, 221 logger, 222 ) 223 if err != nil { 224 return nil, err 225 } 226 if visStore == nil { 227 return nil, nil 228 } 229 return newVisibilityManager( 230 visStore, 231 maxReadQPS, 232 maxWriteQPS, 233 operatorRPSRatio, 234 metricsHandler, 235 metrics.VisibilityPluginNameTag(visStore.GetName()), 236 logger, 237 ), nil 238 } 239 240 func newVisibilityStoreFromDataStoreConfig( 241 dsConfig config.DataStore, 242 persistenceResolver resolver.ServiceResolver, 243 customVisibilityStoreFactory VisibilityStoreFactory, 244 245 esClient esclient.Client, 246 esProcessorConfig *elasticsearch.ProcessorConfig, 247 searchAttributesProvider searchattribute.Provider, 248 searchAttributesMapperProvider searchattribute.MapperProvider, 249 visibilityDisableOrderByClause dynamicconfig.BoolPropertyFnWithNamespaceFilter, 250 visibilityEnableManualPagination dynamicconfig.BoolPropertyFnWithNamespaceFilter, 251 252 metricsHandler metrics.Handler, 253 logger log.Logger, 254 ) (store.VisibilityStore, error) { 255 var ( 256 visStore store.VisibilityStore 257 err error 258 ) 259 if dsConfig.SQL != nil { 260 switch dsConfig.SQL.PluginName { 261 case mysql.PluginNameV8, postgresql.PluginNameV12, postgresql.PluginNameV12PGX, sqlite.PluginName: 262 visStore, err = sql.NewSQLVisibilityStore( 263 *dsConfig.SQL, 264 persistenceResolver, 265 searchAttributesProvider, 266 searchAttributesMapperProvider, 267 logger, 268 ) 269 default: 270 visStore, err = newStandardVisibilityStore( 271 dsConfig, 272 persistenceResolver, 273 searchAttributesProvider, 274 searchAttributesMapperProvider, 275 logger, 276 metricsHandler, 277 ) 278 } 279 } else if dsConfig.Cassandra != nil { 280 visStore, err = newStandardVisibilityStore( 281 dsConfig, 282 persistenceResolver, 283 searchAttributesProvider, 284 searchAttributesMapperProvider, 285 logger, 286 metricsHandler, 287 ) 288 } else if dsConfig.Elasticsearch != nil { 289 visStore = newElasticsearchVisibilityStore( 290 dsConfig.Elasticsearch.GetVisibilityIndex(), 291 esClient, 292 esProcessorConfig, 293 searchAttributesProvider, 294 searchAttributesMapperProvider, 295 visibilityDisableOrderByClause, 296 visibilityEnableManualPagination, 297 metricsHandler, 298 logger, 299 ) 300 } else if dsConfig.CustomDataStoreConfig != nil { 301 visStore, err = customVisibilityStoreFactory.NewVisibilityStore( 302 *dsConfig.CustomDataStoreConfig, 303 persistenceResolver, 304 logger, 305 metricsHandler, 306 ) 307 } 308 return visStore, err 309 } 310 311 func newStandardVisibilityStore( 312 dsConfig config.DataStore, 313 persistenceResolver resolver.ServiceResolver, 314 searchAttributesProvider searchattribute.Provider, 315 searchAttributesMapperProvider searchattribute.MapperProvider, 316 logger log.Logger, 317 metricsHandler metrics.Handler, 318 ) (store.VisibilityStore, error) { 319 var ( 320 visStore store.VisibilityStore 321 err error 322 ) 323 if dsConfig.Cassandra != nil { 324 visStore, err = cassandra.NewVisibilityStore( 325 *dsConfig.Cassandra, 326 persistenceResolver, 327 logger, 328 metricsHandler, 329 ) 330 } else if dsConfig.SQL != nil { 331 visStore, err = standardSql.NewSQLVisibilityStore( 332 *dsConfig.SQL, 333 persistenceResolver, 334 logger, 335 ) 336 } 337 if err != nil { 338 return nil, err 339 } 340 if visStore == nil { 341 logger.Fatal("invalid config: one of cassandra or sql params must be specified for visibility store") 342 return nil, nil 343 } 344 return standard.NewVisibilityStore( 345 visStore, 346 searchAttributesProvider, 347 searchAttributesMapperProvider, 348 ), nil 349 } 350 351 func newElasticsearchVisibilityStore( 352 defaultIndexName string, 353 esClient esclient.Client, 354 esProcessorConfig *elasticsearch.ProcessorConfig, 355 searchAttributesProvider searchattribute.Provider, 356 searchAttributesMapperProvider searchattribute.MapperProvider, 357 visibilityDisableOrderByClause dynamicconfig.BoolPropertyFnWithNamespaceFilter, 358 visibilityEnableManualPagination dynamicconfig.BoolPropertyFnWithNamespaceFilter, 359 metricsHandler metrics.Handler, 360 logger log.Logger, 361 ) store.VisibilityStore { 362 if esClient == nil { 363 return nil 364 } 365 366 var ( 367 esProcessor elasticsearch.Processor 368 esProcessorAckTimeout dynamicconfig.DurationPropertyFn 369 ) 370 if esProcessorConfig != nil { 371 esProcessor = elasticsearch.NewProcessor(esProcessorConfig, esClient, logger, metricsHandler) 372 esProcessor.Start() 373 esProcessorAckTimeout = esProcessorConfig.ESProcessorAckTimeout 374 } 375 s := elasticsearch.NewVisibilityStore( 376 esClient, 377 defaultIndexName, 378 searchAttributesProvider, 379 searchAttributesMapperProvider, 380 esProcessor, 381 esProcessorAckTimeout, 382 visibilityDisableOrderByClause, 383 visibilityEnableManualPagination, 384 metricsHandler) 385 return s 386 }