Skip to content

Refactor pkg/model/enum to Support Decentralized Constant Registration #424

@kyasbal

Description

@kyasbal

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:

  1. High Coupling: Core model code knows about every specific implementation definition (e.g., Cloud Composer specific states are in revision_state.go).
  2. Extensibility Bottleneck: Adding a new parser or task often requires modifying these central files, leading to potential merge conflicts and a lack of modularity.
  3. 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

  1. Design the Registry: Create the Registry generic structure that supports thread-safe registration and metadata lookups.
  2. 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.
  3. Distribute definitions: Move Cloud Provider specific definitions (like GKE, Composer) to their pkg/task/inspection/... packages.
  4. Repeat: Apply to ParentRelationship and RevisionState.

Definition of Done

  • LogType, ParentRelationship, and RevisionState allow dynamic registration.
  • Task specific enum values are defined within their respective task packages.
  • pkg/model/enum no longer contains provider-specific constants.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions