Problem
Currently, pkg/model/enum contains centralized definitions for key domain types:
LogType (in log_type.go)
ParentRelationship (in parent_relationship.go)
RevisionState (in revision_state.go)
These files explicitly list all possible values as int constants and contain large maps defining their frontend metadata (labels, colors, CSS selectors).
Issues with this approach:
- High Coupling: Core model code knows about every specific implementation definition (e.g., Cloud Composer specific states are in
revision_state.go).
- Extensibility Bottleneck: Adding a new parser or task often requires modifying these central files, leading to potential merge conflicts and a lack of modularity.
- Violation of Open-Closed Principle: The core
enum package must be modified every time a new extension requires a new state or relationship.
Proposed Solution
Refactor the enum system to use a Registry Pattern. This will allow inspection tasks to register their own constants and metadata during initialization, decoupling the core model from specific attributes.
1. Registry API
Introduce a mechanism to register values from external packages.
// Conceptual Example
package enum
var logTypeRegistry = NewRegistry[LogType]()
func RegisterLogType(key string, metadata LogTypeFrontendMetadata) LogType {
return logTypeRegistry.Register(key, metadata)
}
2. Decentralization
Move task-specific constants to their relevant packages.
- Example:
RevisionStateComposerTiRunning and its metadata should be defined in pkg/task/inspection/googlecloudcomposer (or similar), not pkg/model/enum.
3. Registration Example
In pkg/task/inspection/.../registration.go, tasks will register their specific types during init().
package impl
import (
"github.com/GoogleCloudPlatform/khi/pkg/model/enum"
"github.com/GoogleCloudPlatform/khi/pkg/task/inspection/googlecloudcomposer/contract"
)
var (
// Store the assigned runtime ID for usage in tasks
RevisionStateComposerTiRunning enum.RevisionState
)
func init() {
RevisionStateComposerTiRunning = enum.RegisterRevisionState(
"RevisionStateComposerTiRunning", // Unique Key
enum.RevisionStateFrontendMetadata{
Label: "Task instance is running",
CSSSelector: "composer_ti_running",
BackgroundColor: "#00ff01",
},
)
// ... register other states
}
4. ID Management
We need to determine safe handling of IDs, as hardcoded int constants will no longer exist for dynamic types.
- Strategy: Embedded Metadata Indexing
- We will continue to use
int for runtime performance and memory efficiency.
- Serialization (.khi files): The file format will be updated to include the necessary frontend metadata (labels, colors, etc.) directly.
- Deserialization: When loading a
.khi file, the IDs in the file will be treated as indices into the embedded metadata list, not the global registry.
- Benefit: This ensures that even if the global registry indices shift (due to different environment configurations or extensions), the file remains valid and self-contained because it carries its own metadata definition.
Migration Strategy
- Design the Registry: Create the
Registry generic structure that supports thread-safe registration and metadata lookups.
- Pilot Refactor: Pick one enum (e.g.,
LogType) and convert it to use the registry.
- Keep existing constants as "Built-in" registrations for backward compatibility during transition.
- Distribute definitions: Move Cloud Provider specific definitions (like GKE, Composer) to their
pkg/task/inspection/... packages.
- Repeat: Apply to
ParentRelationship and RevisionState.
Definition of Done
Problem
Currently,
pkg/model/enumcontains centralized definitions for key domain types:LogType(inlog_type.go)ParentRelationship(inparent_relationship.go)RevisionState(inrevision_state.go)These files explicitly list all possible values as
intconstants and contain large maps defining their frontend metadata (labels, colors, CSS selectors).Issues with this approach:
revision_state.go).enumpackage must be modified every time a new extension requires a new state or relationship.Proposed Solution
Refactor the enum system to use a Registry Pattern. This will allow inspection tasks to register their own constants and metadata during initialization, decoupling the core model from specific attributes.
1. Registry API
Introduce a mechanism to register values from external packages.
2. Decentralization
Move task-specific constants to their relevant packages.
RevisionStateComposerTiRunningand its metadata should be defined inpkg/task/inspection/googlecloudcomposer(or similar), notpkg/model/enum.3. Registration Example
In
pkg/task/inspection/.../registration.go, tasks will register their specific types duringinit().4. ID Management
We need to determine safe handling of IDs, as hardcoded
intconstants will no longer exist for dynamic types.intfor runtime performance and memory efficiency..khifile, the IDs in the file will be treated as indices into the embedded metadata list, not the global registry.Migration Strategy
Registrygeneric structure that supports thread-safe registration and metadata lookups.LogType) and convert it to use the registry.pkg/task/inspection/...packages.ParentRelationshipandRevisionState.Definition of Done
LogType,ParentRelationship, andRevisionStateallow dynamic registration.pkg/model/enumno longer contains provider-specific constants.