Skip to content

Commit cde64d0

Browse files
Richard BaahRichard Baah
authored andcommitted
feat(config file): add config file for frequently changing values
1 parent abb0348 commit cde64d0

19 files changed

+1426
-13
lines changed
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
package config
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"os"
7+
"strings"
8+
9+
"gopkg.in/yaml.v3"
10+
)
11+
12+
var (
13+
kiloByte = 1024
14+
megaByte = 1024 * kiloByte
15+
gigaByte = 1024 * megaByte
16+
)
17+
18+
type Config struct {
19+
Server serverConfig `yaml:"server"`
20+
Batch batchConfig `yaml:"batch"`
21+
Query queryConfig `yaml:"query"`
22+
Metrics metricsConfig `yaml:"metrics"`
23+
}
24+
type serverConfig struct {
25+
Port int `yaml:"port"`
26+
Host string `yaml:"host"`
27+
Timeout int `yaml:"timeout"`
28+
MaxRequestSizeMB uint64 `yaml:"max_request_size_mb"` // max size of a file upload. passed in by grpc request
29+
}
30+
type batchConfig struct {
31+
Size int `yaml:"size"`
32+
EnableParallelRead bool `yaml:"enable_parallel_read"`
33+
MaxMemoryBeforeSplill uint64 `yaml:"max_memory_before_spill"`
34+
MaxFileSizeMB int `yaml:"max_file_size_mb"` // max size of a single file
35+
}
36+
type queryConfig struct {
37+
// should results be cached, server side? if so how long
38+
EnableCache bool `yaml:"enable_cache"`
39+
CacheTTLSeconds int `yaml:"cache_ttl_seconds"`
40+
// run queries concurrently? if so what the max before blocking
41+
EnableConcurrentExecution bool `yaml:"enable_concurrent_execution"`
42+
MaxConcurrentQueries int `yaml:"max_concurrent_queries"` // blocks after this many concurrent queries until one finishes
43+
}
44+
type metricsConfig struct {
45+
EnableMetrics bool `yaml:"enable_metrics"`
46+
MetricsPort int `yaml:"metrics_port"`
47+
MetricsHost string `yaml:"metrics_host"`
48+
ExportIntervalSecs int `yaml:"export_interval_secs"`
49+
// what queries have beeen sent
50+
EnableQueryStats bool `yaml:"enable_query_stats"`
51+
// memory usage over time
52+
EnableMemoryStats bool `yaml:"enable_memory_stats"`
53+
}
54+
55+
var configInstance *Config = &Config{
56+
Server: serverConfig{
57+
Port: 8080,
58+
Host: "localhost",
59+
Timeout: 30,
60+
MaxRequestSizeMB: 15,
61+
},
62+
Batch: batchConfig{
63+
Size: 1024 * 8, // rows per bathch
64+
EnableParallelRead: true,
65+
MaxMemoryBeforeSplill: uint64(gigaByte) * 2, // 2GB
66+
MaxFileSizeMB: 500, // 500MB
67+
},
68+
Query: queryConfig{
69+
EnableCache: true,
70+
CacheTTLSeconds: 600, // 10 minutes
71+
EnableConcurrentExecution: true,
72+
MaxConcurrentQueries: 2, // 2 concurrent queries
73+
},
74+
Metrics: metricsConfig{
75+
EnableMetrics: true,
76+
MetricsPort: 9999,
77+
MetricsHost: "localhost",
78+
ExportIntervalSecs: 60, // 1 minute
79+
EnableQueryStats: true,
80+
EnableMemoryStats: true,
81+
},
82+
}
83+
84+
func GetConfig() *Config {
85+
return configInstance
86+
}
87+
88+
// overwrite global instance with loaded config
89+
func Decode(filePath string) error {
90+
suffix := strings.Split(filePath, ".")[len(strings.Split(filePath, "."))-1]
91+
if suffix != "yaml" && suffix != "yml" {
92+
return errors.New("file must be a .yaml or .yml file")
93+
}
94+
r, err := os.Open(filePath)
95+
if err != nil {
96+
return err
97+
}
98+
config := make(map[string]interface{})
99+
decoder := yaml.NewDecoder(r)
100+
if err := decoder.Decode(config); err != nil {
101+
return fmt.Errorf("failed to decode config: %w", err)
102+
}
103+
fmt.Printf("about to merge from -> %v\n", config)
104+
mergeConfig(configInstance, config)
105+
return nil
106+
}
107+
func mergeConfig(dst *Config, src map[string]interface{}) {
108+
// =============================
109+
// SERVER
110+
// =============================
111+
if server, ok := src["server"].(map[string]interface{}); ok {
112+
if v, ok := server["port"].(int); ok {
113+
dst.Server.Port = v
114+
}
115+
if v, ok := server["host"].(string); ok {
116+
dst.Server.Host = v
117+
}
118+
if v, ok := server["timeout"].(int); ok {
119+
dst.Server.Timeout = v
120+
}
121+
if v, ok := server["max_request_size_mb"].(int); ok {
122+
dst.Server.MaxRequestSizeMB = uint64(v)
123+
}
124+
}
125+
126+
// =============================
127+
// BATCH
128+
// =============================
129+
if batch, ok := src["batch"].(map[string]interface{}); ok {
130+
if v, ok := batch["size"].(int); ok {
131+
dst.Batch.Size = v
132+
}
133+
if v, ok := batch["enable_parallel_read"].(bool); ok {
134+
dst.Batch.EnableParallelRead = v
135+
}
136+
if v, ok := batch["max_memory_before_spill"].(int); ok {
137+
dst.Batch.MaxMemoryBeforeSplill = uint64(v)
138+
}
139+
if v, ok := batch["max_file_size_mb"].(int); ok {
140+
dst.Batch.MaxFileSizeMB = v
141+
}
142+
}
143+
144+
// =============================
145+
// QUERY
146+
// =============================
147+
if query, ok := src["query"].(map[string]interface{}); ok {
148+
if v, ok := query["enable_cache"].(bool); ok {
149+
dst.Query.EnableCache = v
150+
}
151+
if v, ok := query["cache_ttl_seconds"].(int); ok {
152+
dst.Query.CacheTTLSeconds = v
153+
}
154+
if v, ok := query["enable_concurrent_execution"].(bool); ok {
155+
dst.Query.EnableConcurrentExecution = v
156+
}
157+
if v, ok := query["max_concurrent_queries"].(int); ok {
158+
dst.Query.MaxConcurrentQueries = v
159+
}
160+
}
161+
162+
// =============================
163+
// METRICS
164+
// =============================
165+
if metrics, ok := src["metrics"].(map[string]interface{}); ok {
166+
if v, ok := metrics["enable_metrics"].(bool); ok {
167+
dst.Metrics.EnableMetrics = v
168+
}
169+
if v, ok := metrics["metrics_port"].(int); ok {
170+
dst.Metrics.MetricsPort = v
171+
}
172+
if v, ok := metrics["metrics_host"].(string); ok {
173+
dst.Metrics.MetricsHost = v
174+
}
175+
if v, ok := metrics["export_interval_secs"].(int); ok {
176+
dst.Metrics.ExportIntervalSecs = v
177+
}
178+
if v, ok := metrics["enable_query_stats"].(bool); ok {
179+
dst.Metrics.EnableQueryStats = v
180+
}
181+
if v, ok := metrics["enable_memory_stats"].(bool); ok {
182+
dst.Metrics.EnableMemoryStats = v
183+
}
184+
}
185+
}

0 commit comments

Comments
 (0)