func (grm *goRoutineMap) Run( operationName string, operationFunc func() error) error { grm.lock.Lock() defer grm.lock.Unlock() existingOp, exists := grm.operations[operationName] if exists { // Operation with name exists if existingOp.operationPending { return NewAlreadyExistsError(operationName) } if err := existingOp.expBackoff.SafeToRetry(operationName); err != nil { return err } } grm.operations[operationName] = operation{ operationPending: true, expBackoff: existingOp.expBackoff, } go func() (err error) { // Handle unhandled panics (very unlikely) defer k8sRuntime.HandleCrash() // Handle completion of and error, if any, from operationFunc() defer grm.operationComplete(operationName, &err) // Handle panic, if any, from operationFunc() defer k8sRuntime.RecoverFromPanic(&err) return operationFunc() }() return nil }
func (grm *nestedPendingOperations) Run( volumeName v1.UniqueVolumeName, podName types.UniquePodName, operationFunc func() error) error { grm.lock.Lock() defer grm.lock.Unlock() opExists, previousOpIndex := grm.isOperationExists(volumeName, podName) if opExists { previousOp := grm.operations[previousOpIndex] // Operation already exists if previousOp.operationPending { // Operation is pending operationName := getOperationName(volumeName, podName) return NewAlreadyExistsError(operationName) } operationName := getOperationName(volumeName, podName) if err := previousOp.expBackoff.SafeToRetry(operationName); err != nil { return err } // Update existing operation to mark as pending. grm.operations[previousOpIndex].operationPending = true grm.operations[previousOpIndex].volumeName = volumeName grm.operations[previousOpIndex].podName = podName } else { // Create a new operation grm.operations = append(grm.operations, operation{ operationPending: true, volumeName: volumeName, podName: podName, expBackoff: exponentialbackoff.ExponentialBackoff{}, }) } go func() (err error) { // Handle unhandled panics (very unlikely) defer k8sRuntime.HandleCrash() // Handle completion of and error, if any, from operationFunc() defer grm.operationComplete(volumeName, podName, &err) // Handle panic, if any, from operationFunc() defer k8sRuntime.RecoverFromPanic(&err) return operationFunc() }() return nil }