github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/manager/orchestrator/replicated/replicated.go (about)

     1  package replicated
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/docker/swarmkit/api"
     7  	"github.com/docker/swarmkit/manager/orchestrator/restart"
     8  	"github.com/docker/swarmkit/manager/orchestrator/update"
     9  	"github.com/docker/swarmkit/manager/state"
    10  	"github.com/docker/swarmkit/manager/state/store"
    11  )
    12  
    13  // An Orchestrator runs a reconciliation loop to create and destroy
    14  // tasks as necessary for the replicated services.
    15  type Orchestrator struct {
    16  	store *store.MemoryStore
    17  
    18  	reconcileServices map[string]*api.Service
    19  	restartTasks      map[string]struct{}
    20  
    21  	// stopChan signals to the state machine to stop running.
    22  	stopChan chan struct{}
    23  	// doneChan is closed when the state machine terminates.
    24  	doneChan chan struct{}
    25  
    26  	updater  *update.Supervisor
    27  	restarts *restart.Supervisor
    28  
    29  	cluster *api.Cluster // local cluster instance
    30  }
    31  
    32  // NewReplicatedOrchestrator creates a new replicated Orchestrator.
    33  func NewReplicatedOrchestrator(store *store.MemoryStore) *Orchestrator {
    34  	restartSupervisor := restart.NewSupervisor(store)
    35  	updater := update.NewSupervisor(store, restartSupervisor)
    36  	return &Orchestrator{
    37  		store:             store,
    38  		stopChan:          make(chan struct{}),
    39  		doneChan:          make(chan struct{}),
    40  		reconcileServices: make(map[string]*api.Service),
    41  		restartTasks:      make(map[string]struct{}),
    42  		updater:           updater,
    43  		restarts:          restartSupervisor,
    44  	}
    45  }
    46  
    47  // Run contains the orchestrator event loop. It runs until Stop is called.
    48  func (r *Orchestrator) Run(ctx context.Context) error {
    49  	defer close(r.doneChan)
    50  
    51  	// Watch changes to services and tasks
    52  	queue := r.store.WatchQueue()
    53  	watcher, cancel := queue.Watch()
    54  	defer cancel()
    55  
    56  	// Balance existing services and drain initial tasks attached to invalid
    57  	// nodes
    58  	var err error
    59  	r.store.View(func(readTx store.ReadTx) {
    60  		if err = r.initTasks(ctx, readTx); err != nil {
    61  			return
    62  		}
    63  
    64  		if err = r.initServices(readTx); err != nil {
    65  			return
    66  		}
    67  
    68  		if err = r.initCluster(readTx); err != nil {
    69  			return
    70  		}
    71  	})
    72  	if err != nil {
    73  		return err
    74  	}
    75  
    76  	r.tick(ctx)
    77  
    78  	for {
    79  		select {
    80  		case event := <-watcher:
    81  			// TODO(stevvooe): Use ctx to limit running time of operation.
    82  			r.handleTaskEvent(ctx, event)
    83  			r.handleServiceEvent(ctx, event)
    84  			switch v := event.(type) {
    85  			case state.EventCommit:
    86  				r.tick(ctx)
    87  			case api.EventUpdateCluster:
    88  				r.cluster = v.Cluster
    89  			}
    90  		case <-r.stopChan:
    91  			return nil
    92  		}
    93  	}
    94  }
    95  
    96  // Stop stops the orchestrator.
    97  func (r *Orchestrator) Stop() {
    98  	close(r.stopChan)
    99  	<-r.doneChan
   100  	r.updater.CancelAll()
   101  	r.restarts.CancelAll()
   102  }
   103  
   104  func (r *Orchestrator) tick(ctx context.Context) {
   105  	// tickTasks must be called first, so we respond to task-level changes
   106  	// before performing service reconciliation.
   107  	r.tickTasks(ctx)
   108  	r.tickServices(ctx)
   109  }