-
Notifications
You must be signed in to change notification settings - Fork 198
Extend RunConfig with replica and cache-size fields #4203
Description
Description
Add two new fields to RunConfig in pkg/runner/config.go: BackendReplicas *int32 for configuring the desired StatefulSet replica count, and SessionCacheSize int for bounding the local LRU session cache. These fields are the foundation for all horizontal scaling work in the proxyrunner epic — downstream tasks (RC-11, RC-12, RC-13) read these values to control StatefulSet replica management and session cache sizing.
Context
Part of epic stacklok/stacklok-epics#263 — Horizontal Scaling for Proxyrunner (THV-0047). RunConfig is ToolHive's serializable workload configuration and is part of the public API contract. This task extends it with two optional fields that are zero-value-safe: nil BackendReplicas means "don't touch replicas" (preserving HPA/kubectl control), and zero SessionCacheSize will cause consuming code to apply a sensible default of 1000.
Dependencies: None
Blocks: TASK-002 (Configurable StatefulSet replica count), TASK-004 (Implement RoutingStorage)
Acceptance Criteria
-
RunConfigstruct inpkg/runner/config.gohas a newBackendReplicas *int32field with JSON tagjson:"backend_replicas,omitempty"and YAML tagyaml:"backend_replicas,omitempty" -
RunConfigstruct has a newSessionCacheSize intfield with JSON tagjson:"session_cache_size,omitempty"and YAML tagyaml:"session_cache_size,omitempty" - Both fields are optional and zero-value-safe: existing RunConfig JSON/YAML files that do not include the new fields continue to deserialize without error and without changing existing behavior
-
BackendReplicasis a pointer type (*int32) so thatnilcan be distinguished from an explicit value of0 - Doc comments follow the existing field comment style in
RunConfigand explain the nil/zero-value semantics for each field - Round-trip serialization test: a
RunConfigwith both fields set serializes to JSON/YAML and deserializes back with values preserved - Round-trip serialization test: a
RunConfigwithout the new fields (omitted) deserializes withBackendReplicas == nilandSessionCacheSize == 0 - All existing tests pass without modification
Technical Approach
Recommended Implementation
Add the two fields to the RunConfig struct in pkg/runner/config.go, following the existing field ordering and comment conventions. No changes to constructor functions, serialization helpers, or validation logic are needed — the omitempty tags handle backward-compatible serialization, and the zero-value semantics are defined by the consuming code in TASK-002 and TASK-004.
Patterns & Frameworks
- Follow the existing field style in
RunConfig: each field has a Go doc comment, JSON tag, and YAML tag. Fields that are optional useomitemptyon both tags. - Use
*int32(pointer) forBackendReplicasto allow nil-vs-zero distinction, consistent with how Kubernetes API types represent optional integer fields (e.g.,appsv1.StatefulSetSpec.Replicas). - Use plain
int(not a pointer) forSessionCacheSizesince zero is a meaningful sentinel that consuming code maps to a default — consistent with how other integer config fields in the repo are handled. RunConfigis documented as part of ToolHive's API contract (see the struct comment at line 46); do not change the schema versionCurrentSchemaVersionin this PR — these additions are backward-compatible and additive.
Code Pointers
pkg/runner/config.go— TheRunConfigstruct starting at line 46; add the new fields here, following the comment and tag style of existing fields (e.g.,K8sPodTemplatePatchat line 150 is a good nearby example of a Kubernetes-specific optional field with both JSON and YAML tags)pkg/transport/session/storage.go— TheStorageinterface; understanding this helps clarify whySessionCacheSizeis needed (it bounds the LRU cache used byRoutingStoragein TASK-004)pkg/container/kubernetes/client.golines 401–404 — TheWithReplicas(1)call that TASK-002 will make conditional onBackendReplicas != nil
Component Interfaces
The two new fields to add to RunConfig:
// BackendReplicas is the desired StatefulSet replica count for the MCP backend.
// When nil, WithReplicas is omitted from the StatefulSet apply spec so that
// HPA or kubectl retains control of the replica count.
BackendReplicas *int32 `json:"backend_replicas,omitempty" yaml:"backend_replicas,omitempty"`
// SessionCacheSize is the maximum number of sessions held in the proxyrunner's
// local LRU cache. When 0, a default of 1000 is used by the consuming code.
SessionCacheSize int `json:"session_cache_size,omitempty" yaml:"session_cache_size,omitempty"`Testing Strategy
Unit Tests
- Serialize a
RunConfigwithBackendReplicasset to a non-nil value (e.g.,int32(3)) andSessionCacheSizeset to500; unmarshal the JSON output and assert the fields round-trip correctly - Serialize a
RunConfigthat omits both new fields (i.e., zero-valuedRunConfig{}); assert the JSON output does not containbackend_replicasorsession_cache_sizekeys (omitempty behavior) - Deserialize a JSON payload that does not include
backend_replicasorsession_cache_size; assertBackendReplicas == nilandSessionCacheSize == 0 - Deserialize a JSON payload that sets
backend_replicas: 2; assertBackendReplicas != nil && *BackendReplicas == 2
Integration Tests
- No integration tests required for this task — the field additions are structural only and exercised by downstream tasks
Edge Cases
-
backend_replicas: 0in JSON — assert this deserializes toBackendReplicaspointing toint32(0), not nil (important:0is an explicit value distinct from omitted) - YAML round-trip with both fields set — assert values are preserved
Out of Scope
- Validation logic for
BackendReplicasorSessionCacheSize(e.g., range checks) — deferred to consuming code in TASK-002 and TASK-004 - Wiring
BackendReplicasinto the Kubernetes client (TASK-002) - Wiring
SessionCacheSizeintoRoutingStorageconstruction (TASK-004, TASK-006) - Changes to
CurrentSchemaVersion— these fields are backward-compatible additions - CLI flags or operator CRD changes to expose these fields — operator/CLI concerns outside this task
References
- Epic stacklok/stacklok-epics#263: Horizontal Scaling for Proxyrunner (THV-0047)
- RFC THV-0047
pkg/runner/config.go—RunConfigstruct (lines 46–213)pkg/container/kubernetes/client.golines 401–404 — downstream consumer ofBackendReplicaspkg/transport/session/storage.go—Storageinterface; context forSessionCacheSize