refactor: consolidate Instance phase handlers
E2E Tests / Run on Ubuntu (pull_request) Failing after 1m28s
Tests / Run on Ubuntu (pull_request) Successful in 4m35s
Lint / Run on Ubuntu (pull_request) Successful in 4m58s

This commit is contained in:
2026-09-11 15:04:15 +00:00
parent 212ca4be99
commit 89d9e2316b
3 changed files with 164 additions and 103 deletions
@@ -16,58 +16,115 @@ limitations under the License.
package controller
import databasev1alpha1 "git.ddupan.top/panxiao81/postgresql-tenant-operator/api/v1alpha1"
import (
"context"
"errors"
"time"
type instancePhaseResult struct {
phase databasev1alpha1.PostgreSQLInstancePhase
reconcilingMessage string
}
databasev1alpha1 "git.ddupan.top/panxiao81/postgresql-tenant-operator/api/v1alpha1"
ctrl "sigs.k8s.io/controller-runtime"
)
type instancePhaseHandler func(*databasev1alpha1.PostgreSQLInstance) instancePhaseResult
type instancePhaseHandler func(context.Context, *databasev1alpha1.PostgreSQLInstance) (ctrl.Result, error)
type instanceStateMachine struct {
handlers map[databasev1alpha1.PostgreSQLInstancePhase]instancePhaseHandler
initializer PostgreSQLInstanceInitializer
handlers map[databasev1alpha1.PostgreSQLInstancePhase]instancePhaseHandler
}
func newInstanceStateMachine() instanceStateMachine {
return instanceStateMachine{handlers: map[databasev1alpha1.PostgreSQLInstancePhase]instancePhaseHandler{
databasev1alpha1.PostgreSQLInstancePhasePending: reconcileInstancePending,
databasev1alpha1.PostgreSQLInstancePhaseValidating: keepInstancePhase,
databasev1alpha1.PostgreSQLInstancePhaseInitializingRegistry: keepInstancePhase,
databasev1alpha1.PostgreSQLInstancePhaseReady: keepInstancePhase,
databasev1alpha1.PostgreSQLInstancePhaseDeleting: reconcileInstanceDeleting,
}}
func newInstanceStateMachine(initializer PostgreSQLInstanceInitializer) *instanceStateMachine {
m := &instanceStateMachine{initializer: initializer}
m.handlers = map[databasev1alpha1.PostgreSQLInstancePhase]instancePhaseHandler{
databasev1alpha1.PostgreSQLInstancePhasePending: m.pending,
databasev1alpha1.PostgreSQLInstancePhaseValidating: m.validate,
databasev1alpha1.PostgreSQLInstancePhaseInitializingRegistry: m.initializeRegistry,
databasev1alpha1.PostgreSQLInstancePhaseReady: m.ready,
databasev1alpha1.PostgreSQLInstancePhaseDeleting: m.deleting,
}
return m
}
func (m instanceStateMachine) reconcile(instance *databasev1alpha1.PostgreSQLInstance) instancePhaseResult {
func (m *instanceStateMachine) reconcile(ctx context.Context, instance *databasev1alpha1.PostgreSQLInstance) (ctrl.Result, error) {
phase := instance.Status.Phase
if !instance.DeletionTimestamp.IsZero() {
phase = databasev1alpha1.PostgreSQLInstancePhaseDeleting
} else if phase == "" {
phase = databasev1alpha1.PostgreSQLInstancePhasePending
}
handler, found := m.handlers[phase]
if !found {
return instancePhaseResult{phase: phase}
handler = m.pending
}
return handler(instance)
result, err := handler(ctx, instance)
if err != nil {
instance.Status.ObservedGeneration = instance.Generation
reason := databasev1alpha1.ReasonDependencyUnavailable
var categorized interface{ ConditionReason() string }
if errors.As(err, &categorized) {
reason = categorized.ConditionReason()
}
setFailedCondition(&instance.Status.Conditions, instance.Generation, reason, "instance dependency validation failed")
}
return result, err
}
func reconcileInstancePending(*databasev1alpha1.PostgreSQLInstance) instancePhaseResult {
return instancePhaseResult{
phase: databasev1alpha1.PostgreSQLInstancePhaseValidating,
reconcilingMessage: "instance dependencies are being validated",
}
func (m *instanceStateMachine) pending(_ context.Context, instance *databasev1alpha1.PostgreSQLInstance) (ctrl.Result, error) {
return advanceInstance(instance, databasev1alpha1.PostgreSQLInstancePhaseValidating,
"instance dependencies are being validated"), nil
}
func reconcileInstanceDeleting(*databasev1alpha1.PostgreSQLInstance) instancePhaseResult {
return instancePhaseResult{
phase: databasev1alpha1.PostgreSQLInstancePhaseDeleting,
reconcilingMessage: "instance deletion is reconciling",
func (m *instanceStateMachine) validate(ctx context.Context, instance *databasev1alpha1.PostgreSQLInstance) (ctrl.Result, error) {
if m.initializer == nil {
return ctrl.Result{}, nil
}
version, err := m.initializer.Validate(ctx, instance)
if err != nil {
return ctrl.Result{}, err
}
instance.Status.PostgreSQLVersion = version
return advanceInstance(instance, databasev1alpha1.PostgreSQLInstancePhaseInitializingRegistry,
"PostgreSQL registry is being initialized"), nil
}
func keepInstancePhase(instance *databasev1alpha1.PostgreSQLInstance) instancePhaseResult {
return instancePhaseResult{phase: instance.Status.Phase}
func (m *instanceStateMachine) initializeRegistry(ctx context.Context, instance *databasev1alpha1.PostgreSQLInstance) (ctrl.Result, error) {
if m.initializer == nil {
return ctrl.Result{}, nil
}
version, err := m.initializer.InitializeRegistry(ctx, instance)
if err != nil {
return ctrl.Result{}, err
}
instance.Status.PostgreSQLVersion = version
instance.Status.Phase = databasev1alpha1.PostgreSQLInstancePhaseReady
instance.Status.ObservedGeneration = instance.Generation
setReadyCondition(&instance.Status.Conditions, instance.Generation, "instance dependencies are ready")
return ctrl.Result{RequeueAfter: time.Minute}, nil
}
func (m *instanceStateMachine) ready(ctx context.Context, instance *databasev1alpha1.PostgreSQLInstance) (ctrl.Result, error) {
if instance.Status.ObservedGeneration != instance.Generation {
return m.pending(ctx, instance)
}
if m.initializer == nil {
return ctrl.Result{}, nil
}
version, err := m.initializer.Validate(ctx, instance)
if err != nil {
instance.Status.Phase = databasev1alpha1.PostgreSQLInstancePhaseValidating
return ctrl.Result{}, err
}
instance.Status.PostgreSQLVersion = version
return ctrl.Result{RequeueAfter: time.Minute}, nil
}
func (m *instanceStateMachine) deleting(_ context.Context, instance *databasev1alpha1.PostgreSQLInstance) (ctrl.Result, error) {
instance.Status.Phase = databasev1alpha1.PostgreSQLInstancePhaseDeleting
setReconcilingCondition(&instance.Status.Conditions, instance.Generation, "instance deletion is reconciling")
return ctrl.Result{}, nil
}
func advanceInstance(instance *databasev1alpha1.PostgreSQLInstance, phase databasev1alpha1.PostgreSQLInstancePhase, message string) ctrl.Result {
instance.Status.Phase = phase
setReconcilingCondition(&instance.Status.Conditions, instance.Generation, message)
return ctrl.Result{RequeueAfter: time.Millisecond}
}