agent/eventhandler/task_handler.go
func (handler *TaskHandler) taskStateChangesToSend() []api.TaskStateChange {
	handler.lock.RLock()
	defer handler.lock.RUnlock()

	var events []api.TaskStateChange
	for taskARN := range handler.tasksToContainerStates {
		// An entry for the task in tasksToContainerStates means that there
		// is at least 1 container event for that task that hasn't been sent
		// to ECS (has been batched).
		// Make sure that the engine's task state knows about this task (as a
		// safety mechanism) and add it to the list of task state changes
		// that need to be sent to ECS
		if task, ok := handler.state.TaskByArn(taskARN); ok {
			// We do not allow the ticker to submit container state updates for
			// tasks that are STOPPED. This prevents the ticker's asynchronous
			// updates from clobbering container states when the task
			// transitions to STOPPED, since ECS does not allow updates to
			// container states once the task has moved to STOPPED.
			knownStatus := task.GetKnownStatus()
			if knownStatus >= apitaskstatus.TaskStopped {
				continue
			}
			event := api.TaskStateChange{
				TaskARN: taskARN,
				Status:  task.GetKnownStatus(),
				Task:    task,
			}
			event.SetTaskTimestamps()

			events = append(events, event)
		}
	}
	return events
}
func (handler *TaskHandler) taskStateChangesToSend() []api.TaskStateChange {
	handler.lock.RLock()
	defer handler.lock.RUnlock()

	var events []api.TaskStateChange
	for taskARN := range handler.tasksToContainerStates {
		// An entry for the task in tasksToContainerStates means that there
		// is at least 1 container event for that task that hasn't been sent
		// to ECS (has been batched).
		// Make sure that the engine's task state knows about this task (as a
		// safety mechanism) and add it to the list of task state changes
		// that need to be sent to ECS
		if task, ok := handler.state.TaskByArn(taskARN); ok {
			// We do not allow the ticker to submit container state updates for
			// tasks that are STOPPED. This prevents the ticker's asynchronous
			// updates from clobbering container states when the task
			// transitions to STOPPED, since ECS does not allow updates to
			// container states once the task has moved to STOPPED.
			knownStatus := task.GetKnownStatus()
			if knownStatus >= apitaskstatus.TaskStopped {
				continue
			}
			event := api.TaskStateChange{
				TaskARN: taskARN,
				Status:  task.GetKnownStatus(),
				Task:    task,
			}
			event.SetTaskTimestamps()

			events = append(events, event)
		}
	}
	return events
}
// taskStateChangesToSend gets a list task state changes for container events that
// have been batched and not sent beyond the drainEventsFrequency threshold