go.temporal.io/server/common/config/persistence.go
323 LOC · 143 covered · 180 uncovered · 65 ranges · 3012 concepts · 40 introducers · 2174 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 config
import (
"bytes"
"context"
"errors"
"fmt"
"os/exec"
"reflect"
"strings"
"time"
"github.com/gocql/gocql"
"go.temporal.io/server/common/persistence/visibility/store/elasticsearch/client"
)
const (
// StoreTypeSQL refers to sql based storage as persistence store
StoreTypeSQL = "sql"
// StoreTypeNoSQL refers to nosql based storage as persistence store
StoreTypeNoSQL = "nosql"
)
var ErrPersistenceConfig = errors.New("persistence config error")
// DefaultStoreType returns the storeType for the default persistence store
if c.DataStores[c.DefaultStore].SQL != nil {
}
}
// Validate validates the persistence config
stores := []string{c.DefaultStore}
if c.VisibilityStore != "" {
stores = append(stores, c.VisibilityStore)
}
if c.SecondaryVisibilityStore != "" {
stores = append(stores, c.SecondaryVisibilityStore)
}
// There are 3 config keys:
// - visibilityStore: can set any data store
// - secondaryVisibilityStore: can set any data store
// If visibilityStore is set, then it's always the primary.
// If secondaryVisibilityStore is set, it's always the secondary.
//
// Valid dual visibility combinations (order: primary, secondary):
// - visibilityStore (advanced sql), secondaryVisibilityStore (advanced sql)
// - visibilityStore (es), visibilityStore (es) [via elasticsearch.indices config]
// - visibilityStore (es), secondaryVisibilityStore (es)
//
// Invalid dual visibility combinations:
// - visibilityStore (advanced sql), secondaryVisibilityStore (es)
// - visibilityStore (es), secondaryVisibilityStore (advanced sql)
return fmt.Errorf("%w: visibilityStore must be specified", ErrPersistenceConfig)
}
isAnyCustom := c.DataStores[c.VisibilityStore].CustomDataStoreConfig != nil ||
c.DataStores[c.SecondaryVisibilityStore].CustomDataStoreConfig != nil
isPrimaryEs := c.DataStores[c.VisibilityStore].Elasticsearch != nil
isSecondaryEs := c.DataStores[c.SecondaryVisibilityStore].Elasticsearch != nil
if !isAnyCustom && isPrimaryEs != isSecondaryEs {
return fmt.Errorf(
"%w: cannot set visibilityStore and secondaryVisibilityStore with different datastore types",
ErrPersistenceConfig)
}
if c.DataStores[c.VisibilityStore].Elasticsearch.GetSecondaryVisibilityIndex() != "" {
return fmt.Errorf(
"%w: cannot set secondaryVisibilityStore "+
"when visibilityStore is setting Elasticsearch secondary visibility index",
ErrPersistenceConfig)
}
if c.DataStores[c.SecondaryVisibilityStore].Elasticsearch.GetSecondaryVisibilityIndex() != "" {
return fmt.Errorf(
"%w: secondary visibility datastore %q cannot set secondary_visibility",
ErrPersistenceConfig,
c.SecondaryVisibilityStore)
}
}
ds, ok := c.DataStores[st]
if !ok {
return fmt.Errorf("%w: missing config for datastore %q", ErrPersistenceConfig, st)
}
return fmt.Errorf("%w: datastore %q: %s", ErrPersistenceConfig, st, err.Error())
}
}
}
// VisibilityConfigExist returns whether user specified visibilityStore in config
return c.VisibilityStore != ""
}
// SecondaryVisibilityConfigExist returns whether user specified secondaryVisibilityStore in config
return c.SecondaryVisibilityStore != ""
}
func (c *Persistence) IsSQLVisibilityStore() bool {
return (c.VisibilityConfigExist() && c.DataStores[c.VisibilityStore].SQL != nil) ||
(c.SecondaryVisibilityConfigExist() && c.DataStores[c.SecondaryVisibilityStore].SQL != nil)
}
func (c *Persistence) IsCustomVisibilityStore() bool {
return c.GetVisibilityStoreConfig().CustomDataStoreConfig != nil ||
c.GetSecondaryVisibilityStoreConfig().CustomDataStoreConfig != nil
}
return c.DataStores[c.VisibilityStore]
}
if c.SecondaryVisibilityStore != "" {
return c.DataStores[c.SecondaryVisibilityStore]
}
ds := c.DataStores[c.VisibilityStore]
if ds.Elasticsearch != nil && ds.Elasticsearch.GetSecondaryVisibilityIndex() != "" {
esConfig := *ds.Elasticsearch
esConfig.Indices = map[string]string{
client.VisibilityAppName: ds.Elasticsearch.GetSecondaryVisibilityIndex(),
}
ds.Elasticsearch = &esConfig
return ds
}
}
}
switch {
case ds.SQL != nil:
return ds.SQL.DatabaseName
case ds.Cassandra != nil:
return ds.Cassandra.Keyspace
case ds.Elasticsearch != nil:
return ds.Elasticsearch.GetVisibilityIndex()
case ds.CustomDataStoreConfig != nil:
return ds.CustomDataStoreConfig.IndexName
return ""
}
}
// Validate validates the data store config
storeConfigCount := 0
if ds.SQL != nil {
storeConfigCount++
}
if ds.Cassandra != nil {
storeConfigCount++
}
storeConfigCount++
}
storeConfigCount++
}
return errors.New(
"must provide config for one and only one datastore: " +
"elasticsearch, cassandra, sql or custom store",
)
}
if ds.SQL.TaskScanPartitions == 0 {
ds.SQL.TaskScanPartitions = 1
}
if err := ds.SQL.validate(); err != nil {
return err
}
}
if err := ds.Cassandra.validate(); err != nil {
return err
}
}
if err := ds.Elasticsearch.Validate(); err != nil {
return err
}
}
}
// GetConsistency returns the gosql.Consistency setting from the configuration for the given store type
return gocql.ParseConsistency(c.getConsistencySettings().Consistency)
}
// GetSerialConsistency returns the gosql.SerialConsistency setting from the configuration for the store
func (c *CassandraStoreConsistency) GetSerialConsistency() gocql.SerialConsistency {
persistence.go ×2
res, err := parseSerialConsistency(c.getConsistencySettings().SerialConsistency)
if err != nil {
panic(fmt.Sprintf("unable to decode cassandra serial consistency: %v", err))
}
}
func (c *CassandraStoreConsistency) getConsistencySettings() *CassandraConsistencySettings {
persistence.go ×6
return ensureStoreConsistencyNotNil(c).Default
}
func ensureStoreConsistencyNotNil(c *CassandraStoreConsistency) *CassandraStoreConsistency {
persistence.go ×6
if c == nil {
}
}
}
}
}
func (c *Cassandra) validate() error {
return c.Consistency.validate()
}
if c == nil {
}
for _, field := range v.Fields() {
s, ok := field.Interface().(*CassandraConsistencySettings)
if ok {
if err := s.validate(); err != nil {
}
}
}
}
if c == nil {
}
if err != nil {
}
}
if err != nil {
}
}
}
func parseSerialConsistency(serialConsistency string) (gocql.SerialConsistency, error) {
persistence.go ×1
var s gocql.SerialConsistency
err := s.UnmarshalText([]byte(strings.ToUpper(serialConsistency)))
return s, err
}
if c.PasswordCommand != nil && c.Password != "" {
}
}
}
const (
defaultPasswordCommandTimeout = 30 * time.Second
passwordCommandWaitDelay = 5 * time.Second
)
// ResolvePassword returns the database password, either from the static Password
// field or by executing PasswordCommand. If neither is set, it returns an empty string.
if c.PasswordCommand == nil {
}
if timeout == 0 {
}
defer cancel()
cmd := exec.CommandContext(ctx, c.PasswordCommand.Command, c.PasswordCommand.Args...) //nolint:gosec
// WaitDelay caps how long we block on the stdout pipe after the process is killed.
// Without it, a subprocess that inherits the pipe could keep it open indefinitely.
cmd.WaitDelay = passwordCommandWaitDelay
var stderr bytes.Buffer
cmd.Stderr = &stderr
out, err := cmd.Output()
if err != nil {
c.PasswordCommand.Command, c.PasswordCommand.Args, err, stderr.String())
}
}