* Copyright (c) 2024 Huawei Technologies Co., Ltd.
* openFuyao is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package config
import (
"os"
"strings"
"time"
"gopkg.in/yaml.v3"
)
const (
DefaultConfigPath = "/etc/cache-indexer/config.yaml"
)
const (
DefaultHTTPAddr = ":28080"
DefaultHTTPShutdownTimeout = 10 * time.Second
DefaultHTTPReadHeaderTimeout = 10 * time.Second
DefaultHTTPReadTimeout = 30 * time.Second
DefaultHTTPWriteTimeout = 30 * time.Second
DefaultHTTPIdleTimeout = 120 * time.Second
DefaultHTTPMaxHeaderBytes = 1 << 20
DefaultHTTPMaxHitRateBodyBytes = int64(4 << 20)
)
const (
DefaultLogLevel = "info"
)
const (
DefaultPythonHashSeed = "0"
DefaultPrefixCachingHashAlgo = "sha256_cbor"
DefaultUseIntBlockHashes = true
)
const (
DefaultDiscoveryRefreshInterval = 10 * time.Second
DefaultDiscoverySegmentsFetchTimeout = 2 * time.Second
DefaultDiscoveryEngineLabelKey = "openfuyao.com/engine"
DefaultDiscoveryEngineValue = "vllm"
DefaultDiscoveryPDRoleLabelKey = "openfuyao.com/pdRole"
DefaultDiscoveryPDRoleValues = "prefill,aggregate"
DefaultDiscoveryKVManagerLabelKey = "openfuyao.com/kvmanager"
DefaultDiscoveryKVManagerValue = "mooncake"
DefaultVLLMZMQPortName = "zmq-pub"
DefaultMooncakeHTTPPortName = "http-api"
DefaultMooncakeRPCPortName = "rpc"
DefaultMooncakeMasterHTTPPort = 9003
)
const (
DefaultIngestL1BackoffInitial = time.Second
DefaultIngestL1BackoffMax = 30 * time.Second
DefaultIngestL3Scheme = "http"
DefaultIngestL3PollInterval = 10 * time.Second
DefaultIngestL3HTTPTimeout = 5 * time.Second
)
type Settings struct {
HTTP HTTPConfig `yaml:"http"`
Log LogConfig `yaml:"log"`
BlockKey BlockKeyConfig `yaml:"blockKey"`
Discovery DiscoveryConfig `yaml:"discovery"`
Ingest IngestConfig `yaml:"ingest"`
}
type HTTPConfig struct {
Addr string `yaml:"addr"`
ShutdownTimeout time.Duration `yaml:"shutdownTimeout"`
ReadHeaderTimeout time.Duration `yaml:"readHeaderTimeout"`
ReadTimeout time.Duration `yaml:"readTimeout"`
WriteTimeout time.Duration `yaml:"writeTimeout"`
IdleTimeout time.Duration `yaml:"idleTimeout"`
MaxHeaderBytes int `yaml:"maxHeaderBytes"`
MaxHitRateBodyBytes int64 `yaml:"maxHitRateBodyBytes"`
}
type LogConfig struct {
Level string `yaml:"level"`
}
type BlockKeyConfig struct {
PythonHashSeed string `yaml:"pythonHashSeed"`
PrefixCachingHashAlgo string `yaml:"prefixCachingHashAlgo"`
UseIntBlockHashes bool `yaml:"useIntBlockHashes"`
}
type DiscoveryConfig struct {
Namespace string `yaml:"-"`
RefreshInterval time.Duration `yaml:"refreshInterval"`
SegmentsFetchTimeout time.Duration `yaml:"segmentsFetchTimeout"`
Selector DiscoverySelectorConfig `yaml:"labels"`
VLLM VLLMDiscoveryConfig `yaml:"vllm"`
MooncakeMaster MooncakeMasterDiscoveryConfig `yaml:"mooncakeMaster"`
}
type DiscoverySelectorConfig struct {
EngineLabelKey string `yaml:"engineKey"`
EngineValue string `yaml:"engineValue"`
PDRoleLabelKey string `yaml:"pdRoleKey"`
PDRoleValues []string `yaml:"pdRoleValue"`
KVManagerLabelKey string `yaml:"kvManagerKey"`
KVManagerValue string `yaml:"kvManagerValue"`
}
type VLLMDiscoveryConfig struct {
ZMQPortName string `yaml:"zmqPortName"`
}
type MooncakeMasterDiscoveryConfig struct {
HTTPPortName string `yaml:"httpPortName"`
RPCPortName string `yaml:"rpcPortName"`
HTTPPort int32 `yaml:"httpPort"`
RPCPort int32 `yaml:"rpcPort"`
}
type IngestConfig struct {
L1 IngestL1Config `yaml:"l1"`
L3 IngestL3Config `yaml:"l3"`
}
type IngestL1Config struct {
BackoffInitial time.Duration `yaml:"backoffInitial"`
BackoffMax time.Duration `yaml:"backoffMax"`
}
type IngestL3Config struct {
Scheme string `yaml:"scheme"`
PollInterval time.Duration `yaml:"pollInterval"`
HTTPTimeout time.Duration `yaml:"httpTimeout"`
}
func Load() *Settings {
return load(DefaultConfigPath)
}
func load(path string) *Settings {
cfg := defaultSettings()
loadConfigFile(path, cfg)
applyRuntimeEnv(cfg)
return cfg
}
func defaultSettings() *Settings {
return &Settings{
HTTP: defaultHTTPConfig(),
Log: defaultLogConfig(),
BlockKey: defaultBlockKeyConfig(),
Discovery: defaultDiscoveryConfig(),
Ingest: defaultIngestConfig(),
}
}
func defaultHTTPConfig() HTTPConfig {
return HTTPConfig{
Addr: DefaultHTTPAddr,
ShutdownTimeout: DefaultHTTPShutdownTimeout,
ReadHeaderTimeout: DefaultHTTPReadHeaderTimeout,
ReadTimeout: DefaultHTTPReadTimeout,
WriteTimeout: DefaultHTTPWriteTimeout,
IdleTimeout: DefaultHTTPIdleTimeout,
MaxHeaderBytes: DefaultHTTPMaxHeaderBytes,
MaxHitRateBodyBytes: DefaultHTTPMaxHitRateBodyBytes,
}
}
func defaultLogConfig() LogConfig {
return LogConfig{Level: DefaultLogLevel}
}
func defaultBlockKeyConfig() BlockKeyConfig {
return BlockKeyConfig{
PythonHashSeed: DefaultPythonHashSeed,
PrefixCachingHashAlgo: DefaultPrefixCachingHashAlgo,
UseIntBlockHashes: DefaultUseIntBlockHashes,
}
}
func defaultDiscoveryConfig() DiscoveryConfig {
return DiscoveryConfig{
RefreshInterval: DefaultDiscoveryRefreshInterval,
SegmentsFetchTimeout: DefaultDiscoverySegmentsFetchTimeout,
Selector: defaultDiscoverySelectorConfig(),
VLLM: defaultVLLMDiscoveryConfig(),
MooncakeMaster: defaultMooncakeMasterDiscoveryConfig(),
}
}
func defaultDiscoverySelectorConfig() DiscoverySelectorConfig {
return DiscoverySelectorConfig{
EngineLabelKey: DefaultDiscoveryEngineLabelKey,
EngineValue: DefaultDiscoveryEngineValue,
PDRoleLabelKey: DefaultDiscoveryPDRoleLabelKey,
PDRoleValues: splitStringList(DefaultDiscoveryPDRoleValues),
KVManagerLabelKey: DefaultDiscoveryKVManagerLabelKey,
KVManagerValue: DefaultDiscoveryKVManagerValue,
}
}
func defaultVLLMDiscoveryConfig() VLLMDiscoveryConfig {
return VLLMDiscoveryConfig{ZMQPortName: DefaultVLLMZMQPortName}
}
func defaultMooncakeMasterDiscoveryConfig() MooncakeMasterDiscoveryConfig {
return MooncakeMasterDiscoveryConfig{
HTTPPortName: DefaultMooncakeHTTPPortName,
RPCPortName: DefaultMooncakeRPCPortName,
HTTPPort: DefaultMooncakeMasterHTTPPort,
}
}
func defaultIngestConfig() IngestConfig {
return IngestConfig{
L1: defaultIngestL1Config(),
L3: defaultIngestL3Config(),
}
}
func defaultIngestL1Config() IngestL1Config {
return IngestL1Config{
BackoffInitial: DefaultIngestL1BackoffInitial,
BackoffMax: DefaultIngestL1BackoffMax,
}
}
func defaultIngestL3Config() IngestL3Config {
return IngestL3Config{
Scheme: DefaultIngestL3Scheme,
PollInterval: DefaultIngestL3PollInterval,
HTTPTimeout: DefaultIngestL3HTTPTimeout,
}
}
func loadConfigFile(path string, cfg *Settings) {
if path == "" {
return
}
data, err := os.ReadFile(path)
if err != nil || strings.TrimSpace(string(data)) == "" {
return
}
next := *cfg
if err := yaml.Unmarshal(data, &next); err == nil {
*cfg = next
}
}
func applyRuntimeEnv(cfg *Settings) {
if v, ok := os.LookupEnv("POD_NAMESPACE"); ok && v != "" {
cfg.Discovery.Namespace = v
}
}
func splitStringList(v string) []string {
parts := strings.Split(v, ",")
out := make([]string, 0, len(parts))
for _, part := range parts {
part = strings.TrimSpace(part)
if part != "" {
out = append(out, part)
}
}
return out
}