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 }