github.com/verrazzano/verrazzano@v1.7.0/platform-operator/internal/monitor/monitor.go (about)

     1  // Copyright (c) 2022, 2023, Oracle and/or its affiliates.
     2  // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
     3  
     4  package monitor
     5  
     6  import (
     7  	ctrlerrors "github.com/verrazzano/verrazzano/pkg/controller/errors"
     8  )
     9  
    10  // BackgroundProcessMonitor - Represents a monitor object used by the component to monitor a background goroutine used for running
    11  // install, uninstall, etc. operations asynchronously.
    12  type BackgroundProcessMonitor interface {
    13  	// CheckResult - Checks for a result from the goroutine; returns either the result of the operation, or an error indicating
    14  	// the operation is still in progress
    15  	CheckResult() (bool, error)
    16  	// Reset - Resets the monitor and closes any open channels
    17  	Reset()
    18  	// IsRunning - returns true of the monitor/goroutine are active
    19  	IsRunning() bool
    20  	// IsCompleted - returns true if the monitor has run and marked as completed
    21  	IsCompleted() bool
    22  	// SetCompleted - sets the monitor thread to true
    23  	SetCompleted()
    24  	// Run - Run the operation with the specified args in a background goroutine
    25  	Run(operation BackgroundFunc)
    26  }
    27  
    28  // BackgroundFunc - the operation to be called in the background goroutine
    29  type BackgroundFunc func() error
    30  
    31  // BackgroundProcessMonitorType - a monitor. &BackgroundProcessMonitorType acts as an implementation of BackgroundProcessMonitor
    32  type BackgroundProcessMonitorType struct {
    33  	ComponentName string
    34  	running       bool
    35  	completed     bool
    36  	resultCh      chan bool
    37  }
    38  
    39  // CheckResult - checks for a result from the goroutine
    40  // - returns false and a retry error if it's still running, or the result from the channel and nil if an answer was received
    41  func (m *BackgroundProcessMonitorType) CheckResult() (bool, error) {
    42  	select {
    43  	case result := <-m.resultCh:
    44  		return result, nil
    45  	default:
    46  		return false, ctrlerrors.RetryableError{Source: m.ComponentName}
    47  	}
    48  }
    49  
    50  // Reset - reset the monitor and close the channel
    51  func (m *BackgroundProcessMonitorType) Reset() {
    52  	m.running = false
    53  	m.completed = false
    54  	close(m.resultCh)
    55  }
    56  
    57  // IsRunning - returns true if the monitor/goroutine are active
    58  func (m *BackgroundProcessMonitorType) IsRunning() bool {
    59  	return m.running
    60  }
    61  
    62  // IsCompleted - returns true if the monitor/goroutine is completed
    63  func (m *BackgroundProcessMonitorType) IsCompleted() bool {
    64  	return m.completed
    65  }
    66  
    67  // SetCompleted - sets the monitor thread as completed
    68  func (m *BackgroundProcessMonitorType) SetCompleted() {
    69  	m.completed = true
    70  	m.running = false
    71  }
    72  
    73  // Run - calls the operation in a background goroutine
    74  func (m *BackgroundProcessMonitorType) Run(operation BackgroundFunc) {
    75  	m.running = true
    76  	m.resultCh = make(chan bool, 2)
    77  
    78  	go func(outputChan chan bool) {
    79  		// The function will execute once, sending true on success, false on failure to the channel reader
    80  		err := operation()
    81  		if err != nil {
    82  			outputChan <- false
    83  			return
    84  		}
    85  		outputChan <- true
    86  	}(m.resultCh)
    87  }
    88  
    89  // Check that &BackgroundProcessMonitorType implements BackgroundProcessMonitor
    90  var _ BackgroundProcessMonitor = &BackgroundProcessMonitorType{}