Skip to content
Snippets Groups Projects
Select Git revision
  • fed23e159bf6255dba5e7dab81a41440165c6192
  • release default protected
  • 11-22-implement-kv-interface-defined-in-collectiveversionedkvgo
  • hotfix/TestHostPool_UpdateNdf_AddFilter
  • XX-4719/announcementChannels
  • xx-4717/logLevel
  • jonah/noob-channel
  • master protected
  • XX-4707/tagDiskJson
  • xx-4698/notification-retry
  • hotfix/notifylockup
  • syncNodes
  • hotfix/localCB
  • XX-4677/NewChanManagerMobile
  • XX-4689/DmSync
  • duplicatePrefix
  • XX-4601/HavenInvites
  • finalizedUICallbacks
  • XX-4673/AdminKeySync
  • debugNotifID
  • anne/test
  • v4.7.5
  • v4.7.4
  • v4.7.3
  • v4.7.2
  • v4.7.1
  • v4.6.3
  • v4.6.1
  • v4.5.0
  • v4.4.4
  • v4.3.11
  • v4.3.8
  • v4.3.7
  • v4.3.6
  • v4.3.5
  • v4.2.0
  • v4.3.0
  • v4.3.4
  • v4.3.3
  • v4.3.2
  • v4.3.1
41 results

stoppable.go

  • stoppable.go 2.68 KiB
    ///////////////////////////////////////////////////////////////////////////////
    // Copyright © 2020 xx network SEZC                                          //
    //                                                                           //
    // Use of this source code is governed by a license that can be found in the //
    // LICENSE file                                                              //
    ///////////////////////////////////////////////////////////////////////////////
    
    package stoppable
    
    import (
    	"github.com/pkg/errors"
    	jww "github.com/spf13/jwalterweatherman"
    	"strings"
    	"time"
    )
    
    // Error message returned after a comms operations ends and finds that its
    // parent thread is stopping or stopped.
    const (
    	errKey     = "[StoppableNotRunning]"
    	ErrMsg     = "stoppable %q is not running, exiting %s early " + errKey
    	timeoutErr = "timed out after %s waiting for the stoppable to stop for %q"
    )
    
    // pollPeriod is the duration to wait between polls to see of stoppables are
    // stopped.
    const pollPeriod = 100 * time.Millisecond
    
    // Stoppable interface for stopping a goroutine. All functions are thread safe.
    type Stoppable interface {
    	// Name returns the name of the Stoppable.
    	Name() string
    
    	// GetStatus returns the status of the Stoppable.
    	GetStatus() Status
    
    	// IsRunning returns true if the Stoppable is running.
    	IsRunning() bool
    
    	// IsStopping returns true if Stoppable is marked as stopping.
    	IsStopping() bool
    
    	// IsStopped returns true if Stoppable is marked as stopped.
    	IsStopped() bool
    
    	// Close marks the Stoppable as stopping and issues a close signal to the
    	// Stoppable or any children it may have.
    	Close() error
    }
    
    // WaitForStopped polls the stoppable and all its children to see if they are
    // stopped. Returns an error if its times out waiting for all children to stop.
    func WaitForStopped(s Stoppable, timeout time.Duration) error {
    	done := make(chan struct{})
    
    	// Launch the processes to check if all stoppables are stopped in separate
    	// goroutine so that when the timeout is reached, no time is wasted exiting
    	go func() {
    		for !s.IsStopped() {
    			time.Sleep(pollPeriod)
    		}
    
    		select {
    		case done <- struct{}{}:
    		case <-time.NewTimer(50 * time.Millisecond).C:
    		}
    	}()
    
    	select {
    	case <-done:
    		jww.INFO.Printf("All stoppables have stopped for %q.", s.Name())
    		return nil
    	case <-time.NewTimer(timeout).C:
    		return errors.Errorf(timeoutErr, timeout, s.Name())
    	}
    }
    
    // CheckErr returns true if the error contains a stoppable error message. This
    // function is used by callers to determine if a sub function quit due to a
    // stoppable closing and tells the caller to exit.
    func CheckErr(err error) bool {
    	if err == nil {
    		return false
    	}
    	return strings.Contains(err.Error(), errKey)
    }