func (c *Collection) GetStringProperty(key Key, defaultValue string) StringPropertyFn {
	return func(opts ...FilterOption) string {
		val, err := c.client.GetStringValue(key, getFilterMap(opts...), defaultValue)
		if err != nil {
			c.logError(key, err)
		}
		c.logValue(key, val, defaultValue, stringCompareEquals)
		return val
	}
}
GetStringProperty gets property and asserts that it's an string
package dynamicconfig
import (
	"reflect"
	"sync"
	"sync/atomic"
	"time"
	enumspb "go.temporal.io/api/enums/v1"
	"go.temporal.io/server/common/log"
	"go.temporal.io/server/common/log/tag"
)
const (
	errCountLogThreshold = 1000
)
func NewCollection(client Client, logger log.Logger) *Collection {
	return &Collection{
		client:   client,
		logger:   logger,
		keys:     &sync.Map{},
		errCount: -1,
	}
}
type Collection struct {
	client   Client
	logger   log.Logger
	keys     *sync.Map  
	errCount int64
}
func (c *Collection) logError(key Key, err error) {
	errCount := atomic.AddInt64(&c.errCount, 1)
	if errCount%errCountLogThreshold == 0 {
		c.logger.Debug("Failed to fetch key from dynamic config", tag.Key(key.String()), tag.Error(err))
	}
}
func (c *Collection) logValue(
	key Key,
	value, defaultValue interface{},
	cmpValueEquals func(interface{}, interface{}) bool,
) {
	cachedValue, isInCache := c.keys.Load(key)
	if !isInCache || !cmpValueEquals(cachedValue, value) {
		c.keys.Store(key, value)
		c.logger.Info("Get dynamic config", tag.Name(key.String()), tag.Value(value), tag.DefaultValue(defaultValue))
	}
}
type PropertyFn func() interface{}
type IntPropertyFn func(opts ...FilterOption) int
type IntPropertyFnWithNamespaceFilter func(namespace string) int
type IntPropertyFnWithTaskQueueInfoFilters func(namespace string, taskQueue string, taskType enumspb.TaskQueueType) int
type IntPropertyFnWithShardIDFilter func(shardID int32) int
type FloatPropertyFn func(opts ...FilterOption) float64
type FloatPropertyFnWithShardIDFilter func(shardID int32) float64
type FloatPropertyFnWithNamespaceFilter func(namespace string) float64
type FloatPropertyFnWithTaskQueueInfoFilters func(namespace string, taskQueue string, taskType enumspb.TaskQueueType) float64
type DurationPropertyFn func(opts ...FilterOption) time.Duration
type DurationPropertyFnWithNamespaceFilter func(namespace string) time.Duration
type DurationPropertyFnWithNamespaceIDFilter func(namespaceID string) time.Duration
type DurationPropertyFnWithTaskQueueInfoFilters func(namespace string, taskQueue string, taskType enumspb.TaskQueueType) time.Duration
type DurationPropertyFnWithShardIDFilter func(shardID int32) time.Duration
type BoolPropertyFn func(opts ...FilterOption) bool
type StringPropertyFn func(opts ...FilterOption) string
type MapPropertyFn func(opts ...FilterOption) map[string]interface{}
type StringPropertyFnWithNamespaceFilter func(namespace string) string
type MapPropertyFnWithNamespaceFilter func(namespace string) map[string]interface{}
type BoolPropertyFnWithNamespaceFilter func(namespace string) bool
type BoolPropertyFnWithNamespaceIDFilter func(id string) bool
type BoolPropertyFnWithTaskQueueInfoFilters func(namespace string, taskQueue string, taskType enumspb.TaskQueueType) bool
func (c *Collection) GetProperty(key Key, defaultValue interface{}) PropertyFn {
	return func() interface{} {
		val, err := c.client.GetValue(key, defaultValue)
		if err != nil {
			c.logError(key, err)
		}
		c.logValue(key, val, defaultValue, reflect.DeepEqual)
		return val
	}
}
func getFilterMap(opts ...FilterOption) map[Filter]interface{} {
	l := len(opts)
	m := make(map[Filter]interface{}, l)
	for _, opt := range opts {
		opt(m)
	}
	return m
}
func (c *Collection) GetIntProperty(key Key, defaultValue int) IntPropertyFn {
	return func(opts ...FilterOption) int {
		val, err := c.client.GetIntValue(key, getFilterMap(opts...), defaultValue)
		if err != nil {
			c.logError(key, err)
		}
		c.logValue(key, val, defaultValue, intCompareEquals)
		return val
	}
}
func (c *Collection) GetIntPropertyFilteredByNamespace(key Key, defaultValue int) IntPropertyFnWithNamespaceFilter {
	return func(namespace string) int {
		val, err := c.client.GetIntValue(key, getFilterMap(NamespaceFilter(namespace)), defaultValue)
		if err != nil {
			c.logError(key, err)
		}
		c.logValue(key, val, defaultValue, intCompareEquals)
		return val
	}
}
func (c *Collection) GetIntPropertyFilteredByTaskQueueInfo(key Key, defaultValue int) IntPropertyFnWithTaskQueueInfoFilters {
	return func(namespace string, taskQueue string, taskType enumspb.TaskQueueType) int {
		val := defaultValue
		var err error
		filterMaps := []map[Filter]interface{}{
			getFilterMap(NamespaceFilter(namespace), TaskQueueFilter(taskQueue), TaskTypeFilter(taskType)),
			getFilterMap(NamespaceFilter(namespace), TaskQueueFilter(taskQueue)),
		}
		for _, filterMap := range filterMaps {
			val, err = c.client.GetIntValue(
				key,
				filterMap,
				defaultValue,
			)
			if err != nil {
				c.logError(key, err)
			}
			if val != defaultValue {
				break
			}
		}
		c.logValue(key, val, defaultValue, intCompareEquals)
		return val
	}
}
func (c *Collection) GetIntPropertyFilteredByShardID(key Key, defaultValue int) IntPropertyFnWithShardIDFilter {
	return func(shardID int32) int {
		val, err := c.client.GetIntValue(
			key,
			getFilterMap(ShardIDFilter(shardID)),
			defaultValue,
		)
		if err != nil {
			c.logError(key, err)
		}
		c.logValue(key, val, defaultValue, intCompareEquals)
		return val
	}
}
func (c *Collection) GetFloat64Property(key Key, defaultValue float64) FloatPropertyFn {
	return func(opts ...FilterOption) float64 {
		val, err := c.client.GetFloatValue(key, getFilterMap(opts...), defaultValue)
		if err != nil {
			c.logError(key, err)
		}
		c.logValue(key, val, defaultValue, float64CompareEquals)
		return val
	}
}
func (c *Collection) GetFloat64PropertyFilteredByShardID(key Key, defaultValue float64) FloatPropertyFnWithShardIDFilter {
	return func(shardID int32) float64 {
		val, err := c.client.GetFloatValue(
			key,
			getFilterMap(ShardIDFilter(shardID)),
			defaultValue,
		)
		if err != nil {
			c.logError(key, err)
		}
		c.logValue(key, val, defaultValue, float64CompareEquals)
		return val
	}
}
func (c *Collection) GetFloatPropertyFilteredByNamespace(key Key, defaultValue float64) FloatPropertyFnWithNamespaceFilter {
	return func(namespace string) float64 {
		val, err := c.client.GetFloatValue(key, getFilterMap(NamespaceFilter(namespace)), defaultValue)
		if err != nil {
			c.logError(key, err)
		}
		c.logValue(key, val, defaultValue, float64CompareEquals)
		return val
	}
}
func (c *Collection) GetFloatPropertyFilteredByTaskQueueInfo(key Key, defaultValue float64) FloatPropertyFnWithTaskQueueInfoFilters {
	return func(namespace string, taskQueue string, taskType enumspb.TaskQueueType) float64 {
		val := defaultValue
		var err error
		filterMaps := []map[Filter]interface{}{
			getFilterMap(NamespaceFilter(namespace), TaskQueueFilter(taskQueue), TaskTypeFilter(taskType)),
			getFilterMap(NamespaceFilter(namespace), TaskQueueFilter(taskQueue)),
		}
		for _, filterMap := range filterMaps {
			val, err = c.client.GetFloatValue(
				key,
				filterMap,
				defaultValue,
			)
			if err != nil {
				c.logError(key, err)
			}
			if val != defaultValue {
				break
			}
		}
		c.logValue(key, val, defaultValue, float64CompareEquals)
		return val
	}
}
func (c *Collection) GetDurationProperty(key Key, defaultValue time.Duration) DurationPropertyFn {
	return func(opts ...FilterOption) time.Duration {
		val, err := c.client.GetDurationValue(key, getFilterMap(opts...), defaultValue)
		if err != nil {
			c.logError(key, err)
		}
		c.logValue(key, val, defaultValue, durationCompareEquals)
		return val
	}
}
func (c *Collection) GetDurationPropertyFilteredByNamespace(key Key, defaultValue time.Duration) DurationPropertyFnWithNamespaceFilter {
	return func(namespace string) time.Duration {
		val, err := c.client.GetDurationValue(key, getFilterMap(NamespaceFilter(namespace)), defaultValue)
		if err != nil {
			c.logError(key, err)
		}
		c.logValue(key, val, defaultValue, durationCompareEquals)
		return val
	}
}
func (c *Collection) GetDurationPropertyFilteredByNamespaceID(key Key, defaultValue time.Duration) DurationPropertyFnWithNamespaceIDFilter {
	return func(namespaceID string) time.Duration {
		val, err := c.client.GetDurationValue(key, getFilterMap(NamespaceIDFilter(namespaceID)), defaultValue)
		if err != nil {
			c.logError(key, err)
		}
		c.logValue(key, val, defaultValue, durationCompareEquals)
		return val
	}
}
func (c *Collection) GetDurationPropertyFilteredByTaskQueueInfo(key Key, defaultValue time.Duration) DurationPropertyFnWithTaskQueueInfoFilters {
	return func(namespace string, taskQueue string, taskType enumspb.TaskQueueType) time.Duration {
		val := defaultValue
		var err error
		filterMaps := []map[Filter]interface{}{
			getFilterMap(NamespaceFilter(namespace), TaskQueueFilter(taskQueue), TaskTypeFilter(taskType)),
			getFilterMap(NamespaceFilter(namespace), TaskQueueFilter(taskQueue)),
		}
		for _, filterMap := range filterMaps {
			val, err = c.client.GetDurationValue(
				key,
				filterMap,
				defaultValue,
			)
			if err != nil {
				c.logError(key, err)
			}
			if val != defaultValue {
				break
			}
		}
		c.logValue(key, val, defaultValue, durationCompareEquals)
		return val
	}
}
func (c *Collection) GetDurationPropertyFilteredByShardID(key Key, defaultValue time.Duration) DurationPropertyFnWithShardIDFilter {
	return func(shardID int32) time.Duration {
		val, err := c.client.GetDurationValue(
			key,
			getFilterMap(ShardIDFilter(shardID)),
			defaultValue,
		)
		if err != nil {
			c.logError(key, err)
		}
		c.logValue(key, val, defaultValue, durationCompareEquals)
		return val
	}
}
func (c *Collection) GetBoolProperty(key Key, defaultValue bool) BoolPropertyFn {
	return func(opts ...FilterOption) bool {
		val, err := c.client.GetBoolValue(key, getFilterMap(opts...), defaultValue)
		if err != nil {
			c.logError(key, err)
		}
		c.logValue(key, val, defaultValue, boolCompareEquals)
		return val
	}
}