code: func (gc *GarbageCollector) attemptToOrphanWorker() bool {
  	item, quit := gc.attemptToOrphan.Get()
  	gc.workerLock.RLock()
  	defer gc.workerLock.RUnlock()
  	if quit {
  		return false
  	}
  	defer gc.attemptToOrphan.Done(item)
  	owner, ok := item.(*node)
  	if !ok {
  		utilruntime.HandleError(fmt.Errorf("expect *node, got %#v", item))
  		return true
  	}
  	// we don't need to lock each element, because they never get updated
  	owner.dependentsLock.RLock()
  	dependents := make([]*node, 0, len(owner.dependents))
  	for dependent := range owner.dependents {
  		dependents = append(dependents, dependent)
  	}
  	owner.dependentsLock.RUnlock()
  
  	err := gc.orphanDependents(owner.identity, dependents)
  	if err != nil {
  		utilruntime.HandleError(fmt.Errorf("orphanDependents for %s failed with %v", owner.identity, err))
  		gc.attemptToOrphan.AddRateLimited(item)
  		return true
  	}
  	// update the owner, remove "orphaningFinalizer" from its finalizers list
  	err = gc.removeFinalizer(owner, metav1.FinalizerOrphanDependents)
  	if err != nil {
  		utilruntime.HandleError(fmt.Errorf("removeOrphanFinalizer for %s failed with %v", owner.identity, err))
  		gc.attemptToOrphan.AddRateLimited(item)
  	}
  	return true
  }
docs: // attemptToOrphanWorker dequeues a node from the attemptToOrphan, then finds its
  // dependents based on the graph maintained by the GC, then removes it from the
  // OwnerReferences of its dependents, and finally updates the owner to remove
  // the "Orphan" finalizer. The node is added back into the attemptToOrphan if any of
  // these steps fail.