public function run(PayloadInterface $payload)
    {
        $tasks = $this->getTaskCollection()->getTasks();
        $tasksCount = $tasks->count();

        if (0 === $tasksCount) {
            throw new LogicException('Can\'t invoke task run. Empty task collection set.');
        }

        $this->log(LogLevel::INFO, sprintf('Starting runner with %s tasks ready for execution.', $tasksCount));
        $this->dispatch('runner.start', null, $payload);

        foreach ($tasks as $task) {
            try {
                /** @var TaskInterface $task */
                $task->setPayload($payload);
                $this->runTask($task, $payload);
            } catch (\Exception $e) {
                $this->logTask(
                    $task,
                    LogLevel::ERROR,
                    sprintf('An exception was thrown. Message: %s', $e->getMessage())
                );
                $this->dispatch('runner.failure', null, null, null, $e);
                throw new RunFailedException(
                    'Complete run failed: ' . $e->getMessage(),
                    $e->getCode(),
                    $e
                );
            }
        }

        $this->log(LogLevel::INFO, 'All tasks were processed.');
        $this->log(LogLevel::INFO, 'Calling attached runners.');
        $this->notify($payload);

        $this->log(LogLevel::INFO, 'Execution successful.');
        $this->dispatch('runner.success', null, $payload);

        return $payload;
    }