/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package statefulset

import (
	"context"
	"fmt"
	"reflect"
	"time"

	apps "k8s.io/api/apps/v1"
	v1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
	"k8s.io/apimachinery/pkg/util/wait"
	appsinformers "k8s.io/client-go/informers/apps/v1"
	coreinformers "k8s.io/client-go/informers/core/v1"
	clientset "k8s.io/client-go/kubernetes"
	"k8s.io/client-go/kubernetes/scheme"
	v1core "k8s.io/client-go/kubernetes/typed/core/v1"
	appslisters "k8s.io/client-go/listers/apps/v1"
	corelisters "k8s.io/client-go/listers/core/v1"
	"k8s.io/client-go/tools/cache"
	"k8s.io/client-go/tools/record"
	"k8s.io/client-go/util/workqueue"
	podutil "k8s.io/kubernetes/pkg/api/v1/pod"
	"k8s.io/kubernetes/pkg/controller"
	"k8s.io/kubernetes/pkg/controller/history"
)

// controllerKind contains the schema.GroupVersionKind for this controller type.
var controllerKind = apps.SchemeGroupVersion.WithKind("StatefulSet")

// StatefulSetController controls statefulsets.
type StatefulSetController struct {
	// client interface
	kubeClient clientset.Interface
	// control returns an interface capable of syncing a stateful set.
	// Abstracted out for testing.
	control StatefulSetControlInterface
	// podControl is used for patching pods.
	podControl controller.PodControlInterface
	// podLister is able to list/get pods from a shared informer's store
	podLister corelisters.PodLister
	// podListerSynced returns true if the pod shared informer has synced at least once
	podListerSynced cache.InformerSynced
	// setLister is able to list/get stateful sets from a shared informer's store
	setLister appslisters.StatefulSetLister
	// setListerSynced returns true if the stateful set shared informer has synced at least once
	setListerSynced cache.InformerSynced
	// pvcListerSynced returns true if the pvc shared informer has synced at least once
	pvcListerSynced cache.InformerSynced
	// revListerSynced returns true if the rev shared informer has synced at least once
	revListerSynced cache.InformerSynced
	// StatefulSets that need to be synced.
	queue workqueue.RateLimitingInterface
	// eventBroadcaster is the core of event processing pipeline.
	eventBroadcaster record.EventBroadcaster
}

// 这段Go代码定义了一个名为StatefulSetController的结构体,用于控制StatefulSets。
// 它包含了一系列的成员变量,包括client接口、控制StatefulSet同步的接口、用于patching pods的接口、以及一系列的Lister和Synced函数,
// 用于从共享informer的存储中获取Pods、StatefulSets、PVCs等信息。
// 此外,它还定义了一个工作队列和一个事件广播器。这个结构体主要用于管理和同步Kubernetes中的StatefulSets。
// NewStatefulSetController creates a new statefulset controller.
func NewStatefulSetController(
	ctx context.Context,
	podInformer coreinformers.PodInformer,
	setInformer appsinformers.StatefulSetInformer,
	pvcInformer coreinformers.PersistentVolumeClaimInformer,
	revInformer appsinformers.ControllerRevisionInformer,
	kubeClient clientset.Interface,
) *StatefulSetController {
	logger := klog.FromContext(ctx)
	eventBroadcaster := record.NewBroadcaster(record.WithContext(ctx))
	recorder := eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "statefulset-controller"})
	ssc := &StatefulSetController{
		kubeClient: kubeClient,
		control: NewDefaultStatefulSetControl(
			NewStatefulPodControl(
				kubeClient,
				podInformer.Lister(),
				pvcInformer.Lister(),
				recorder),
			NewRealStatefulSetStatusUpdater(kubeClient, setInformer.Lister()),
			history.NewHistory(kubeClient, revInformer.Lister()),
			recorder,
		),
		pvcListerSynced: pvcInformer.Informer().HasSynced,
		revListerSynced: revInformer.Informer().HasSynced,
		queue:           workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "statefulset"),
		podControl:      controller.RealPodControl{KubeClient: kubeClient, Recorder: recorder},

		eventBroadcaster: eventBroadcaster,
	}
	//该函数用于创建一个新的StatefulSet控制器。它接收多个参数,包括上下文、各种Informer、客户端接口等。
	//函数内部通过调用NewDefaultStatefulSetControl函数和其他函数,初始化了StatefulSetController结构体的各个字段,
	//并返回一个指向StatefulSetController结构体的指针。
	podInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
		// lookup the statefulset and enqueue
		AddFunc: func(obj interface{}) {
			ssc.addPod(logger, obj)
		},
		// lookup current and old statefulset if labels changed
		UpdateFunc: func(oldObj, newObj interface{}) {
			ssc.updatePod(logger, oldObj, newObj)
		},
		// lookup statefulset accounting for deletion tombstones
		DeleteFunc: func(obj interface{}) {
			ssc.deletePod(logger, obj)
		},
	})
	//这段代码定义了一个Go函数,它为podInformer的Informer添加了一个事件处理程序。
	//该事件处理程序使用cache.ResourceEventHandlerFuncs结构体中的AddFunc、UpdateFunc和DeleteFunc来处理资源的添加、更新和删除事件。
	//- AddFunc函数在资源添加时调用ssc.addPod(logger, obj)来添加Pod。
	//- UpdateFunc函数在资源更新时调用ssc.updatePod(logger, oldObj, newObj)来更新Pod。
	//- DeleteFunc函数在资源删除时调用ssc.deletePod(logger, obj)来删除Pod。
	//这些函数通过传入的logger和相应的资源对象来执行具体的操作。
	ssc.podLister = podInformer.Lister()
	ssc.podListerSynced = podInformer.Informer().HasSynced

	setInformer.Informer().AddEventHandler(
		cache.ResourceEventHandlerFuncs{
			AddFunc: ssc.enqueueStatefulSet,
			UpdateFunc: func(old, cur interface{}) {
				oldPS := old.(*apps.StatefulSet)
				curPS := cur.(*apps.StatefulSet)
				if oldPS.Status.Replicas != curPS.Status.Replicas {
					logger.V(4).Info("Observed updated replica count for StatefulSet", "statefulSet", klog.KObj(curPS), "oldReplicas", oldPS.Status.Replicas, "newReplicas", curPS.Status.Replicas)
				}
				ssc.enqueueStatefulSet(cur)
			},
			DeleteFunc: ssc.enqueueStatefulSet,
		},
	)
	//这段代码主要涉及到了Kubernetes Informer机制的使用,用于监听StatefulSet资源的变化,并对变化事件进行处理。
	//1. 首先,ssc.podLister = podInformer.Lister()和ssc.podListerSynced = podInformer.Informer().HasSynced
	//两行代码是将pod的Lister和是否同步完成的函数赋值给ssc对象的对应字段。Lister是用来从Informer的cache中获取资源列表和单个资源的,
	//HasSynced则是用来判断Informer是否已经完成初始的资源同步。
	//2. 接下来,setInformer.Informer().AddEventHandler(...)这行代码是给setInformer添加了一个事件处理函数。
	//其中,cache.ResourceEventHandlerFuncs是一个包含了资源添加、更新和删除事件处理函数的结构体。
	//- AddFunc: ssc.enqueueStatefulSet表示当有StatefulSet资源被添加时,调用ssc.enqueueStatefulSet函数来处理该事件。
	//- UpdateFunc表示当有StatefulSet资源被更新时,会先判断其副本数是否发生了变化,如果有变化则打印日志并调用ssc.enqueueStatefulSet函数来处理该事件。
	//- DeleteFunc: ssc.enqueueStatefulSet表示当有StatefulSet资源被删除时,调用ssc.enqueueStatefulSet函数来处理该事件。
	//综上所述,这段代码通过使用Kubernetes Informer机制监听StatefulSet资源的变化,并调用ssc.enqueueStatefulSet函数来处理这些变化事件。
	ssc.setLister = setInformer.Lister()
	ssc.setListerSynced = setInformer.Informer().HasSynced

	// TODO: Watch volumes
	return ssc
}

// 这个Go函数主要设置了ssc对象的setLister和setListerSynced属性。
// setLister是通过setInformer.Lister()方法设置的,它用于从存储中获取设置列表。setListerSynced是通过setInformer.Informer().HasSynced方法设置的,
// 它用于检查设置的同步状态。最后,该函数返回ssc对象。
// Run runs the statefulset controller.
func (ssc *StatefulSetController) Run(ctx context.Context, workers int) {
	defer utilruntime.HandleCrash()

	// Start events processing pipeline.
	ssc.eventBroadcaster.StartStructuredLogging(3)
	ssc.eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: ssc.kubeClient.CoreV1().Events("")})
	defer ssc.eventBroadcaster.Shutdown()

	defer ssc.queue.ShutDown()

	logger := klog.FromContext(ctx)
	logger.Info("Starting stateful set controller")
	defer logger.Info("Shutting down statefulset controller")
	//该函数是StatefulSetController类型的Run方法,用于启动statefulset控制器。
	//函数首先处理崩溃情况,然后开启事件处理管道,记录事件并将其发送到事件接收器。
	//之后,函数通过调用queue的ShutDown方法来关闭队列。函数在启动和关闭控制器时分别记录日志信息。
	if !cache.WaitForNamedCacheSync("stateful set", ctx.Done(), ssc.podListerSynced, ssc.setListerSynced, ssc.pvcListerSynced, ssc.revListerSynced) {
		return
	}

	for i := 0; i < workers; i++ {
		go wait.UntilWithContext(ctx, ssc.worker, time.Second)
	}

	<-ctx.Done()
}

// 这段Go代码主要实现了以下功能:
// - 等待多个缓存同步完成:通过调用cache.WaitForNamedCacheSync方法,
// 等待podListerSynced、setListerSynced、pvcListerSynced和revListerSynced四个缓存同步完成。
// 如果在指定的上下文ctx被取消或超时之前,所有缓存都已同步,则继续执行后续代码;否则直接返回。
// - 启动多个工作协程:使用for循环和go关键字,启动workers个工作协程,并在每个协程中定期执行ssc.worker函数,其间隔时间为1秒。
// 这些工作协程会一直运行,直到上下文ctx被取消或超时。
// - 等待上下文取消或超时:通过读取ctx.Done()通道,阻塞当前协程,等待上下文ctx被取消或超时。
// 一旦上下文被取消或超时,整个函数执行结束。  这段代码通常用于在启动时等待多个缓存同步完成,并启动多个工作协程来处理后续任务。
// 通过上下文ctx来控制整个函数的运行时长,并能够在缓存同步或工作协程运行过程中随时取消操作。
// addPod adds the statefulset for the pod to the sync queue
func (ssc *StatefulSetController) addPod(logger klog.Logger, obj interface{}) {
	pod := obj.(*v1.Pod)

	if pod.DeletionTimestamp != nil {
		// on a restart of the controller manager, it's possible a new pod shows up in a state that
		// is already pending deletion. Prevent the pod from being a creation observation.
		ssc.deletePod(logger, pod)
		return
	}

	// If it has a ControllerRef, that's all that matters.
	if controllerRef := metav1.GetControllerOf(pod); controllerRef != nil {
		set := ssc.resolveControllerRef(pod.Namespace, controllerRef)
		if set == nil {
			return
		}
		logger.V(4).Info("Pod created with labels", "pod", klog.KObj(pod), "labels", pod.Labels)
		ssc.enqueueStatefulSet(set)
		return
	}
	//该函数是StatefulSetController类型的一个方法,用于将Pod的状态添加到同步队列中。
	//首先,它检查Pod是否已被标记为删除,如果是,则调用deletePod方法删除Pod,并返回。
	//然后,它检查Pod是否有ControllerRef,如果有,则通过resolveControllerRef方法解析ControllerRef,
	//并将解析结果传递给enqueueStatefulSet方法,以将StatefulSet添加到同步队列中。
	// Otherwise, it's an orphan. Get a list of all matching controllers and sync
	// them to see if anyone wants to adopt it.
	sets := ssc.getStatefulSetsForPod(pod)
	if len(sets) == 0 {
		return
	}
	logger.V(4).Info("Orphan Pod created with labels", "pod", klog.KObj(pod), "labels", pod.Labels)
	for _, set := range sets {
		ssc.enqueueStatefulSet(set)
	}
}

// 该函数用于处理一个无归属的Pod(孤儿Pod),通过获取与该Pod匹配的所有StatefulSet控制器,并将它们同步,以查看是否有控制器愿意“收养”这个Pod。
// 首先,函数会调用ssc.getStatefulSetsForPod(pod)方法来获取与Pod匹配的所有StatefulSet集合。
// 如果这个集合的长度为0,说明没有找到匹配的控制器,那么函数直接返回。
// 否则,函数会使用logger记录一条日志信息,以4级日志级别记录“创建了一个孤儿Pod,并列出了Pod的标签”。
// 然后,函数会遍历这个匹配的StatefulSet集合,对每个集合调用ssc.enqueueStatefulSet(set)方法,将其加入到同步队列中,以便后续进行同步处理。
// updatePod adds the statefulset for the current and old pods to the sync queue.
func (ssc *StatefulSetController) updatePod(logger klog.Logger, old, cur interface{}) {
	curPod := cur.(*v1.Pod)
	oldPod := old.(*v1.Pod)
	if curPod.ResourceVersion == oldPod.ResourceVersion {
		// In the event of a re-list we may receive update events for all known pods.
		// Two different versions of the same pod will always have different RVs.
		return
	}

	labelChanged := !reflect.DeepEqual(curPod.Labels, oldPod.Labels)

	curControllerRef := metav1.GetControllerOf(curPod)
	oldControllerRef := metav1.GetControllerOf(oldPod)
	controllerRefChanged := !reflect.DeepEqual(curControllerRef, oldControllerRef)
	if controllerRefChanged && oldControllerRef != nil {
		// The ControllerRef was changed. Sync the old controller, if any.
		if set := ssc.resolveControllerRef(oldPod.Namespace, oldControllerRef); set != nil {
			ssc.enqueueStatefulSet(set)
		}
	}
	//该函数用于将当前和旧的Pod的状态fulset添加到同步队列中。
	//函数首先将传入的old和cur参数转换为v1.Pod类型,并检查它们的ResourceVersion是否相同。
	//如果相同,则表示这是由于重新列表而导致的更新事件,函数将直接返回。
	//然后,函数会检查Pod的标签是否发生变化,并检查ControllerRef是否发生变化。
	//如果ControllerRef发生变化且旧的ControllerRef不为空,则函数将解析旧的ControllerRef,并将对应的StatefulSet添加到同步队列中。
	// If it has a ControllerRef, that's all that matters.
	if curControllerRef != nil {
		set := ssc.resolveControllerRef(curPod.Namespace, curControllerRef)
		if set == nil {
			return
		}
		logger.V(4).Info("Pod objectMeta updated", "pod", klog.KObj(curPod), "oldObjectMeta", oldPod.ObjectMeta, "newObjectMeta", curPod.ObjectMeta)
		ssc.enqueueStatefulSet(set)
		// TODO: MinReadySeconds in the Pod will generate an Available condition to be added in
		// the Pod status which in turn will trigger a requeue of the owning replica set thus
		// having its status updated with the newly available replica.
		if !podutil.IsPodReady(oldPod) && podutil.IsPodReady(curPod) && set.Spec.MinReadySeconds > 0 {
			logger.V(2).Info("StatefulSet will be enqueued after minReadySeconds for availability check", "statefulSet", klog.KObj(set), "minReadySeconds", set.Spec.MinReadySeconds)
			// Add a second to avoid milliseconds skew in AddAfter.
			// See https://github.com/kubernetes/kubernetes/issues/39785#issuecomment-279959133 for more info.
			ssc.enqueueSSAfter(set, (time.Duration(set.Spec.MinReadySeconds)*time.Second)+time.Second)
		}
		return
	}
	//该Go函数是一个处理Pod对象元数据更新的函数。
	//它首先检查当前Pod是否有ControllerRef,如果有,则通过resolveControllerRef方法解析其引用的Controller,并将其加入到队列中以进行后续处理。
	//如果Pod满足特定条件(例如,从不可用状态变为可用状态,并且其所属的StatefulSet的MinReadySeconds大于0),
	//则会将StatefulSet加入到队列中, 以便在MinReadySeconds秒后进行可用性检查。
	// Otherwise, it's an orphan. If anything changed, sync matching controllers
	// to see if anyone wants to adopt it now.
	if labelChanged || controllerRefChanged {
		sets := ssc.getStatefulSetsForPod(curPod)
		if len(sets) == 0 {
			return
		}
		logger.V(4).Info("Orphan Pod objectMeta updated", "pod", klog.KObj(curPod), "oldObjectMeta", oldPod.ObjectMeta, "newObjectMeta", curPod.ObjectMeta)
		for _, set := range sets {
			ssc.enqueueStatefulSet(set)
		}
	}
}

// 这段Go代码是处理Pod对象的元数据更新的逻辑。
// 如果Pod的标签或控制器引用发生了变化,它会检查是否有StatefulSet控制器可以“收养”这个Pod。
// 如果有,则将这个StatefulSet控制器加入到队列中,以便进一步处理。
// deletePod enqueues the statefulset for the pod accounting for deletion tombstones.
func (ssc *StatefulSetController) deletePod(logger klog.Logger, obj interface{}) {
	pod, ok := obj.(*v1.Pod)

	// When a delete is dropped, the relist will notice a pod in the store not
	// in the list, leading to the insertion of a tombstone object which contains
	// the deleted key/value. Note that this value might be stale.
	if !ok {
		tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
		if !ok {
			utilruntime.HandleError(fmt.Errorf("couldn't get object from tombstone %+v", obj))
			return
		}
		pod, ok = tombstone.Obj.(*v1.Pod)
		if !ok {
			utilruntime.HandleError(fmt.Errorf("tombstone contained object that is not a pod %+v", obj))
			return
		}
	}
	//该函数是一个Go语言函数,名为deletePod,它属于StatefulSetController类型。
	//该函数的功能是将删除操作对应的状态fulset加入到队列中,并考虑到删除标记(tombstones)。
	//函数参数: - logger:klog.Logger类型,用于记录日志。
	//- obj:interface{}类型,表示要删除的Pod对象。
	//函数流程: 1. 尝试将obj对象转换为*v1.Pod类型。
	//2. 如果转换失败,则尝试将obj对象转换为cache.DeletedFinalStateUnknown类型。
	//3. 如果转换成功,则从tombstone对象中获取被删除的Pod对象。
	//4. 如果获取失败,则记录错误信息并返回。
	//5. 如果成功获取到Pod对象,则将其加入到队列中,以供后续处理。
	//该函数主要处理了两种情况:直接删除Pod对象和通过tombstone对象删除Pod。
	//在处理过程中,函数会进行类型断言来确保对象类型正确,并在出现异常时记录错误信息。
	controllerRef := metav1.GetControllerOf(pod)
	if controllerRef == nil {
		// No controller should care about orphans being deleted.
		return
	}
	set := ssc.resolveControllerRef(pod.Namespace, controllerRef)
	if set == nil {
		return
	}
	logger.V(4).Info("Pod deleted.", "pod", klog.KObj(pod), "caller", utilruntime.GetCaller())
	ssc.enqueueStatefulSet(set)
}

// 该函数是一个Go语言函数,名为deletePod,它属于StatefulSetController类型。
// 该函数的功能是在删除Pod时,检查是否有对应的控制器(StatefulSet)对该Pod有管理关系,
// 如果有,则将该StatefulSet加入到队列中,以触发相应的更新操作。
// 函数流程:
// 1. 通过metav1.GetControllerOf函数获取Pod的控制器引用(controllerRef)。
// 2. 如果controllerRef为nil,表示该Pod没有对应的控制器,则直接返回。
// 3. 调用ssc.resolveControllerRef函数解析controllerRef,获取对应的StatefulSet对象(set)。
// 4. 如果set为nil,表示无法解析到对应的StatefulSet,则直接返回。
// 5. 记录日志信息,表示Pod已被删除。
// 6. 将set加入到队列中,以触发StatefulSet的更新操作。
// 该函数主要通过controllerRef来确定Pod所属的StatefulSet,并在删除Pod时,通知对应的StatefulSet进行相应的更新操作。
// 如果无法确定Pod的控制器或者无法解析到对应的StatefulSet,则函数直接返回,不做任何处理。
// getPodsForStatefulSet returns the Pods that a given StatefulSet should manage.
// It also reconciles ControllerRef by adopting/orphaning.
//
// NOTE: Returned Pods are pointers to objects from the cache.
// If you need to modify one, you need to copy it first.
func (ssc *StatefulSetController) getPodsForStatefulSet(ctx context.Context, set *apps.StatefulSet, selector labels.Selector) ([]*v1.Pod, error) {
	// List all pods to include the pods that don't match the selector anymore but
	// has a ControllerRef pointing to this StatefulSet.
	pods, err := ssc.podLister.Pods(set.Namespace).List(labels.Everything())
	if err != nil {
		return nil, err
	}

	filter := func(pod *v1.Pod) bool {
		// Only claim if it matches our StatefulSet name. Otherwise release/ignore.
		return isMemberOf(set, pod)
	}

	cm := controller.NewPodControllerRefManager(ssc.podControl, set, selector, controllerKind, ssc.canAdoptFunc(ctx, set))
	return cm.ClaimPods(ctx, pods, filter)
}

// 该函数用于获取指定StatefulSet应该管理的Pods,并通过adopting/orphaning来协调ControllerRef。
// 函数首先从缓存中列出所有Pods,包括不再匹配选择器但具有指向该StatefulSet的ControllerRef的Pods。
// 然后通过isMemberOf函数筛选出属于该StatefulSet的Pods。
// 最后,使用PodControllerRefManager的ClaimPods方法来处理ControllerRef的采用/孤儿化,并返回属于该StatefulSet的Pods的指针。
// 注意:返回的Pods是来自缓存的对象指针,如果需要修改,则需要先复制。
// If any adoptions are attempted, we should first recheck for deletion with
// an uncached quorum read sometime after listing Pods/ControllerRevisions (see #42639).
func (ssc *StatefulSetController) canAdoptFunc(ctx context.Context, set *apps.StatefulSet) func(ctx2 context.Context) error {
	return controller.RecheckDeletionTimestamp(func(ctx context.Context) (metav1.Object, error) {
		fresh, err := ssc.kubeClient.AppsV1().StatefulSets(set.Namespace).Get(ctx, set.Name, metav1.GetOptions{})
		if err != nil {
			return nil, err
		}
		if fresh.UID != set.UID {
			return nil, fmt.Errorf("original StatefulSet %v/%v is gone: got uid %v, wanted %v", set.Namespace, set.Name, fresh.UID, set.UID)
		}
		return fresh, nil
	})
}

// 该函数是一个生成函数,返回一个函数,用于检查是否有资格收养(adopt)某个StatefulSet。
// 收养的条件是:在尝试收养之后,需要再次使用未缓存的多数读取(uncached quorum read)检查该StatefulSet是否已被删除。
// 函数内部通过调用ssc.kubeClient.AppsV1().StatefulSets(set.Namespace).Get()来获取最新的StatefulSet信息,并与原有信息进行对比,
// 如果UID一致,则返回最新的StatefulSet对象;否则返回错误信息。
// adoptOrphanRevisions adopts any orphaned ControllerRevisions matched by set's Selector.
func (ssc *StatefulSetController) adoptOrphanRevisions(ctx context.Context, set *apps.StatefulSet) error {
	revisions, err := ssc.control.ListRevisions(set)
	if err != nil {
		return err
	}
	orphanRevisions := make([]*apps.ControllerRevision, 0)
	for i := range revisions {
		if metav1.GetControllerOf(revisions[i]) == nil {
			orphanRevisions = append(orphanRevisions, revisions[i])
		}
	}
	if len(orphanRevisions) > 0 {
		canAdoptErr := ssc.canAdoptFunc(ctx, set)(ctx)
		if canAdoptErr != nil {
			return fmt.Errorf("can't adopt ControllerRevisions: %v", canAdoptErr)
		}
		return ssc.control.AdoptOrphanRevisions(set, orphanRevisions)
	}
	return nil
}

// 该函数用于收养被控制器创建但没有被任何StatefulSet认领的ControllerRevision对象。具体流程如下:
// 1. 调用ssc.control.ListRevisions(set)获取与给定StatefulSet相关联的所有ControllerRevision对象。
// 2. 遍历所有ControllerRevision对象,如果其metav1.GetControllerOf字段为空,则将其加入orphanRevisions列表。
// 3. 如果orphanRevisions列表非空,则调用ssc.canAdoptFunc(ctx, set)(ctx)判断是否可以收养这些孤儿Revision。
// 4. 如果可以收养,则调用ssc.control.AdoptOrphanRevisions(set, orphanRevisions)进行收养操作。
// 5. 如果收养过程中出现错误,则返回错误信息;否则返回nil表示成功。
// getStatefulSetsForPod returns a list of StatefulSets that potentially match
// a given pod.
func (ssc *StatefulSetController) getStatefulSetsForPod(pod *v1.Pod) []*apps.StatefulSet {
	sets, err := ssc.setLister.GetPodStatefulSets(pod)
	if err != nil {
		return nil
	}
	// More than one set is selecting the same Pod
	if len(sets) > 1 {
		// ControllerRef will ensure we don't do anything crazy, but more than one
		// item in this list nevertheless constitutes user error.
		setNames := []string{}
		for _, s := range sets {
			setNames = append(setNames, s.Name)
		}
		utilruntime.HandleError(
			fmt.Errorf(
				"user error: more than one StatefulSet is selecting pods with labels: %+v. Sets: %v",
				pod.Labels, setNames))
	}
	return sets
}

// 该函数用于获取与给定Pod相匹配的所有StatefulSet列表。
// - 首先,函数通过调用ssc.setLister.GetPodStatefulSets(pod)方法获取选择该Pod的所有StatefulSet。
// - 如果获取过程中出现错误,则直接返回nil。
// - 如果存在多个StatefulSet选择同一个Pod(即sets长度大于1),则将其视为用户错误。
// 函数会记录错误信息,并返回所有匹配的StatefulSet列表。
// 注意:在存在多个StatefulSet选择同一个Pod时,通过ControllerRef可以确保不会发生疯狂的行为。
// 但是多个StatefulSet出现在列表中仍然被认为是用户错误。
// resolveControllerRef returns the controller referenced by a ControllerRef,
// or nil if the ControllerRef could not be resolved to a matching controller
// of the correct Kind.
func (ssc *StatefulSetController) resolveControllerRef(namespace string, controllerRef *metav1.OwnerReference) *apps.StatefulSet {
	// We can't look up by UID, so look up by Name and then verify UID.
	// Don't even try to look up by Name if it's the wrong Kind.
	if controllerRef.Kind != controllerKind.Kind {
		return nil
	}
	set, err := ssc.setLister.StatefulSets(namespace).Get(controllerRef.Name)
	if err != nil {
		return nil
	}
	if set.UID != controllerRef.UID {
		// The controller we found with this Name is not the same one that the
		// ControllerRef points to.
		return nil
	}
	return set
}

// 该函数用于解析ControllerRef引用的控制器,如果引用无法解析为正确的类型,则返回nil。
// 具体步骤如下: 1. 检查controllerRef的类型是否与期望的类型相匹配,如果不匹配则直接返回nil。
// 2. 通过名称查找StatefulSet控制器,如果查找失败则返回nil。
// 3. 验证找到的StatefulSet控制器的UID是否与controllerRef的UID相同,如果不同则返回nil。
// 4. 如果以上验证都通过,则返回找到的StatefulSet控制器。
// enqueueStatefulSet enqueues the given statefulset in the work queue.
func (ssc *StatefulSetController) enqueueStatefulSet(obj interface{}) {
	key, err := controller.KeyFunc(obj)
	if err != nil {
		utilruntime.HandleError(fmt.Errorf("couldn't get key for object %+v: %v", obj, err))
		return
	}
	ssc.queue.Add(key)
}

// 该函数用于将给定的状态fulset对象加入工作队列中。
// 函数首先通过controller.KeyFunc方法获取对象的键值,如果获取失败,则通过utilruntime.HandleError方法记录错误信息并返回。
// 最后,将获取到的键值加入到ssc.queue队列中。
// enqueueStatefulSet enqueues the given statefulset in the work queue after given time
func (ssc *StatefulSetController) enqueueSSAfter(ss *apps.StatefulSet, duration time.Duration) {
	key, err := controller.KeyFunc(ss)
	if err != nil {
		utilruntime.HandleError(fmt.Errorf("couldn't get key for object %#v: %v", ss, err))
		return
	}
	ssc.queue.AddAfter(key, duration)
}

// 该函数将给定的状态集(StatefulSet)在指定时间后加入到工作队列中。
// 首先,函数通过调用controller.KeyFunc(ss)方法获取状态集的键值。
// 如果获取键值时出现错误,则使用utilruntime.HandleError()方法处理错误并返回。
// 最后,将键值和指定时间间隔添加到ssc.queue队列中,以便后续处理。
// processNextWorkItem dequeues items, processes them, and marks them done. It enforces that the syncHandler is never
// invoked concurrently with the same key.
func (ssc *StatefulSetController) processNextWorkItem(ctx context.Context) bool {
	key, quit := ssc.queue.Get()
	if quit {
		return false
	}
	defer ssc.queue.Done(key)
	if err := ssc.sync(ctx, key.(string)); err != nil {
		utilruntime.HandleError(fmt.Errorf("error syncing StatefulSet %v, requeuing: %v", key.(string), err))
		ssc.queue.AddRateLimited(key)
	} else {
		ssc.queue.Forget(key)
	}
	return true
}

// 该函数是一个处理工作项的函数,它从队列中获取工作项,处理它,并将其标记为完成。
// 它确保同步处理程序永远不会使用相同的键并发执行。
// 函数返回一个布尔值,表示是否继续处理下一个工作项。
// worker runs a worker goroutine that invokes processNextWorkItem until the controller's queue is closed
func (ssc *StatefulSetController) worker(ctx context.Context) {
	for ssc.processNextWorkItem(ctx) {
	}
}

// 该函数是一个goroutine,用于不断调用processNextWorkItem处理工作项,直到控制器的队列关闭。
// sync syncs the given statefulset.
func (ssc *StatefulSetController) sync(ctx context.Context, key string) error {
	startTime := time.Now()
	logger := klog.FromContext(ctx)
	defer func() {
		logger.V(4).Info("Finished syncing statefulset", "key", key, "time", time.Since(startTime))
	}()

	namespace, name, err := cache.SplitMetaNamespaceKey(key)
	//该函数是一个Go语言函数,它定义在名为StatefulSetController的结构体中,使用sync作为函数名。
	//该函数接收两个参数:ctx context.Context和key string,并返回一个error类型的值。
	//函数主要功能如下:
	//1. 记录开始时间:在函数开始处,通过调用time.Now()记录当前时间,用于后续计算函数执行时间。
	//2. 获取日志记录器:通过从传入的ctx参数中获取日志记录器,用于记录函数执行的日志信息。
	//3. 延迟执行日志记录:使用defer关键字定义延迟执行的函数,该函数会在函数返回前执行。
	//延迟函数主要记录函数执行结束时间,并通过日志记录器记录函数执行时间及关键参数信息。
	//4. 分解键值:通过调用cache.SplitMetaNamespaceKey(key)函数,将传入的键值key分解为命名空间namespace和名称name两个部分。
	//整体而言,该函数的主要作用是同步处理某个键值对应的StatefulSet对象,具体处理逻辑在该函数的后续代码中实现。
	//该函数通过记录函数执行时间、获取日志记录器以及分解键值等操作,为后续处理提供了必要信息。
	if err != nil {
		return err
	}
	set, err := ssc.setLister.StatefulSets(namespace).Get(name)
	//该函数主要执行以下操作:
	//1. 检查err是否为nil,如果不为nil,则直接返回错误。
	//2. 调用ssc.setLister.StatefulSets(namespace).Get(name)获取指定命名空间中的状态集,并将其赋值给set变量。
	//3. 返回set和err,其中set为获取的状态集,err为执行过程中可能出现的错误。
	if errors.IsNotFound(err) {
		logger.Info("StatefulSet has been deleted", "key", key)
		return nil
	}
	//这段Go代码主要进行错误判断和日志记录。具体功能如下:
	//- 首先,它检查错误变量err是否为NotFound错误(即该错误表示某个资源未找到)。
	//- 如果是NotFound错误,它会通过logger.Info方法记录一条日志信息,指示某个StatefulSet已被删除,同时在日志中包含key参数的值。
	//- 最后,函数返回nil,表示处理完成且无需进一步处理。
	//这段代码的作用是在遇到特定类型的错误时,记录一条相关日志信息,并终止进一步的错误处理流程。
	if err != nil {
		utilruntime.HandleError(fmt.Errorf("unable to retrieve StatefulSet %v from store: %v", key, err))
		return err
	}
	//这段Go代码是一个错误处理的示例。
	//如果变量err不为nil,则会使用utilruntime.HandleError()函数处理错误,
	//该函数会将一个格式化后的错误信息打印出来。然后函数会返回err。这段代码的作用是在发生错误时记录错误信息并返回错误。
	selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector)
	if err != nil {
		utilruntime.HandleError(fmt.Errorf("error converting StatefulSet %v selector: %v", key, err))
		// This is a non-transient error, so don't retry.
		return nil
	}
	//这段Go代码主要实现了将StatefulSet的标签选择器转换为Selector的功能。
	//具体来说,它首先通过metav1.LabelSelectorAsSelector函数将set.Spec.Selector转换为Selector类型,
	//如果转换过程中出现错误,则通过utilruntime.HandleError函数记录错误信息,并返回nil。
	//需要注意的是,这里的错误被认为是非瞬时错误,因此不会进行重试。
	if err := ssc.adoptOrphanRevisions(ctx, set); err != nil {
		return err
	}
	//这个函数调用了ssc.adoptOrphanRevisions方法,该方法的作用是在给定的上下文ctx中采用孤儿修订版本。如果方法执行出错,则会返回错误信息err。
	pods, err := ssc.getPodsForStatefulSet(ctx, set, selector)
	if err != nil {
		return err
	}
	//该函数尝试通过调用ssc.getPodsForStatefulSet方法获取与指定StatefulSet和选择器相关联的Pods。如果获取过程中出现错误,则将错误返回。
	return ssc.syncStatefulSet(ctx, set, pods)
	//该函数是Go语言编写的,用于同步更新StatefulSet(有状态副本集)的状态。
	//- ctx是一个上下文对象,用于控制函数执行的生命周期。
	//- set是一个StatefulSet对象,表示要更新的有状态副本集。
	//- pods是一个Pod对象的列表,表示有状态副本集中的Pods。
	//函数内部会根据传入的有状态副本集和Pods对象,进行一系列操作来更新副本集的状态,使其与实际的Pods状态保持一致。具体操作细节可以根据函数实现来确定。
}

// syncStatefulSet syncs a tuple of (statefulset, []*v1.Pod).
func (ssc *StatefulSetController) syncStatefulSet(ctx context.Context, set *apps.StatefulSet, pods []*v1.Pod) error {
	logger := klog.FromContext(ctx)
	logger.V(4).Info("Syncing StatefulSet with pods", "statefulSet", klog.KObj(set), "pods", len(pods))
	var status *apps.StatefulSetStatus
	var err error
	status, err = ssc.control.UpdateStatefulSet(ctx, set, pods)
	if err != nil {
		return err
	}
	logger.V(4).Info("Successfully synced StatefulSet", "statefulSet", klog.KObj(set))
	// One more sync to handle the clock skew. This is also helping in requeuing right after status update
	if set.Spec.MinReadySeconds > 0 && status != nil && status.AvailableReplicas != *set.Spec.Replicas {
		ssc.enqueueSSAfter(set, time.Duration(set.Spec.MinReadySeconds)*time.Second)
	}

	return nil
}

//该函数是一个用于同步StatefulSet和其关联Pods的函数。
//它通过调用ssc.control.UpdateStatefulSet方法来更新StatefulSet的状态,
//并在更新完成后进行额外的同步操作来处理时钟偏移。
//如果StatefulSet的MinReadySeconds大于0,并且更新后的状态的AvailableReplicas与Spec.Replicas不相等,则会重新排队等待处理。