// FinalSave should be called immediately before exiting, and only before // exiting, in order to flush tasks to disk. It waits a short timeout for state // to settle if necessary. If unable to reach a steady-state and save within // this short timeout, it returns an error func FinalSave(saver statemanager.Saver, taskEngine engine.TaskEngine) error { engineDisabled := make(chan error) disableTimer := time.AfterFunc(engineDisableTimeout, func() { engineDisabled <- errors.New("Timed out waiting for TaskEngine to settle") }) go func() { log.Debug("Shutting down task engine") taskEngine.Disable() disableTimer.Stop() engineDisabled <- nil }() disableErr := <-engineDisabled stateSaved := make(chan error) saveTimer := time.AfterFunc(finalSaveTimeout, func() { stateSaved <- errors.New("Timed out trying to save to disk") }) go func() { log.Debug("Saving state before shutting down") stateSaved <- saver.ForceSave() saveTimer.Stop() }() saveErr := <-stateSaved if disableErr != nil || saveErr != nil { return utils.NewMultiError(disableErr, saveErr) } return nil }
// handlePayloadMessage attempts to add each task to the taskengine and, if it can, acks the request. func handlePayloadMessage(responseChan chan<- string, cluster, containerInstanceArn string, payload *ecsacs.PayloadMessage, taskEngine engine.TaskEngine, client api.ECSClient, saver statemanager.Saver) { if payload.MessageId == nil { log.Crit("Recieved a payload with no message id", "payload", payload) return } allTasksHandled := addPayloadTasks(client, cluster, containerInstanceArn, payload, taskEngine) // save the state of tasks we know about after passing them to the task engine err := saver.Save() if err != nil { log.Error("Error saving state for payload message!", "err", err, "messageId", *payload.MessageId) // Don't ack; maybe we can save it in the future. return } if allTasksHandled { go func() { // Throw the ack in async; it doesn't really matter all that much and this is blocking handling more tasks. responseChan <- *payload.MessageId }() // Record the sequence number as well if payload.SeqNum != nil { SequenceNumber.Set(*payload.SeqNum) } } }