Skip to content

[Refactor] Rename service/controller packages, split env_instance, and decouple engine interfaces #25

@lanmaoxinqing

Description

@lanmaoxinqing

Checklist

  • This refactor maintains backward compatibility with all user-facing APIs.
  • For large-scale refactors, I’ve prepared a phased implementation plan.

Current Limitations

The current Go module structure and package naming do not clearly reflect their responsibilities or abstraction levels, leading to confusion and tight coupling:

  • service package is misnamed — it acts as the core execution engine, not a generic service layer.
  • controller implies MVC semantics that don’t fully align with Go's idiomatic API design; it serves as the HTTP/gRPC entrypoint layer.
  • service/env_instance.go mixes interface definition (EnvInstance) with concrete implementation, making it hard to swap out backends or write clean unit tests.
  • schedule_client is ambiguously named and hides its actual purpose: managing sandboxed environments on Kubernetes.
  • Import paths and dependencies are tightly coupled, increasing the cost of future engine extensibility (e.g., adding Ray, Docker, or E2B backends).

These issues hinder code readability, testability, and long-term maintainability.

Proposed Refactor

Refactor package names and internal structure to improve clarity, enforce separation between interface and implementation, and support future pluggable engines:

  1. Rename serviceengine

    • Update package name and directory: pkg/servicepkg/engine
    • All types like ServiceClient, NewService()EngineClient, NewEngine()
    • Benefit: Clearer domain semantics — this package encapsulates execution logic, not general-purpose services.
  2. Rename controllerapi

    • Update: pkg/controllerpkg/api
    • Refactor HTTP handlers and routers accordingly (e.g., Controller.ServeHTTPAPI.Serve)
    • Benefit: More accurately represents the role as the external-facing interface layer.
  3. Split service/env_instance.go into two files under engine:

    • env_instance_interface.go:
      type EnvInstance interface {
          Start(ctx context.Context) error
          Stop(ctx context.Context) error
          Exec(ctx context.Context, cmd []string) ([]byte, error)
          // ...
      }
    • standard_engine_client.go:
      Implements EnvInstance with current logic.
    • Move interface to be part of engine package; keep implementation concrete but decoupled.
    • Benefit: Enables mocking in tests and paves the way for alternative implementations (e.g., ray_engine_client, e2b_engine_client).
  4. Rename schedule_clientk8s_sandbox_client

    • File and package: pkg/schedule_clientpkg/k8s_sandbox_client
    • Type: ScheduleClientK8SSandboxClient
    • Clearly signals Kubernetes + sandboxing context.
    • Benefit: Prevents misinterpretation and improves discoverability.
  5. Update all internal imports and dependency references

    • Use IDE-assisted refactoring or gopls rename / go mod edit where applicable.
    • Ensure no circular dependencies are introduced.
    • Validate with go build ./... and go test ./... post-refactor.

Benefits:

  • Clearer architecture: api depends on engine, which depends on interfaces, not concrete clients.
  • Supports upcoming multi-engine strategy via interface-based design.
  • More idiomatic Go structure with explicit abstractions.
  • Easier testing and dependency injection.

Alternatives Considered

  • Introduce intermediate facade instead of renaming:
    Could wrap old packages, but would add unnecessary indirection and delay necessary cleanup.

  • Use versioned packages (e.g., v2) for backward compatibility:
    Not needed — all affected packages are internal (pkg/...), with no external module exposure or tagged releases depending on them.

  • Keep combined env_instance file with internal interface:
    Violates Go best practices for large interfaces; splitting improves clarity and aligns with standard library patterns (e.g., io.Reader, http.Handler).

Additional Context

This change supports the roadmap for pluggable sandbox engines (see #123).
Related discussion: Design Proposal: Pluggable Execution Engines

🔧 Implementation Notes (Go-specific):

  • Use gopls or gomodifytags + goimports to safely update references.
  • Consider adding //go:build ignore or feature flags if rolling out in phases.
  • Update any documentation, examples, or README.md referencing old package names.

📌 Next Steps:

  1. Open draft PR with proposed directory and package renames.
  2. Run linter and CI pipeline to catch import errors early.
  3. Add interface-based unit tests to validate abstraction quality.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions