feat: add MultipleOptionsTask

This is a variation of a Sequential Task, in which a subtask failing
will prompt the next one to execute, and a subtask being successful will
stop the task.

This way, this can be used for easily managing fallbacks with tasks. :D

Signed-off-by: flow <flowlnlnln@gmail.com>
This commit is contained in:
flow 2022-06-02 19:34:08 -03:00
parent dd6aabf9ab
commit 9a44c92211
No known key found for this signature in database
GPG Key ID: 8D0F221F0A59F469
4 changed files with 76 additions and 7 deletions

View File

@ -397,6 +397,8 @@ set(TASKS_SOURCES
tasks/ConcurrentTask.cpp tasks/ConcurrentTask.cpp
tasks/SequentialTask.h tasks/SequentialTask.h
tasks/SequentialTask.cpp tasks/SequentialTask.cpp
tasks/MultipleOptionsTask.h
tasks/MultipleOptionsTask.cpp
) )
ecm_add_test(tasks/Task_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test ecm_add_test(tasks/Task_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test

View File

@ -0,0 +1,48 @@
#include "MultipleOptionsTask.h"
#include <QDebug>
MultipleOptionsTask::MultipleOptionsTask(QObject* parent, const QString& task_name) : SequentialTask(parent, task_name) {}
void MultipleOptionsTask::startNext()
{
Task* previous = nullptr;
if (m_currentIndex != -1) {
previous = m_queue[m_currentIndex].get();
disconnect(previous, 0, this, 0);
}
m_currentIndex++;
if ((previous && previous->wasSuccessful())) {
emitSucceeded();
return;
}
Task::Ptr next = m_queue[m_currentIndex];
connect(next.get(), &Task::failed, this, &MultipleOptionsTask::subTaskFailed);
connect(next.get(), &Task::succeeded, this, &MultipleOptionsTask::startNext);
connect(next.get(), &Task::status, this, &MultipleOptionsTask::subTaskStatus);
connect(next.get(), &Task::stepStatus, this, &MultipleOptionsTask::subTaskStatus);
connect(next.get(), &Task::progress, this, &MultipleOptionsTask::subTaskProgress);
qDebug() << QString("Making attemp %1 out of %2").arg(m_currentIndex + 1).arg(m_queue.size());
setStatus(tr("Making attempt #%1 out of %2").arg(m_currentIndex + 1).arg(m_queue.size()));
setStepStatus(next->isMultiStep() ? next->getStepStatus() : next->getStatus());
next->start();
}
void MultipleOptionsTask::subTaskFailed(QString const& reason)
{
qDebug() << QString("Failed attempt #%1 of %2. Reason: %3").arg(m_currentIndex + 1).arg(m_queue.size()).arg(reason);
if(m_currentIndex < m_queue.size() - 1) {
startNext();
return;
}
qWarning() << QString("All attempts have failed!");
emitFailed();
}

View File

@ -0,0 +1,19 @@
#pragma once
#include "SequentialTask.h"
/* This task type will attempt to do run each of it's subtasks in sequence,
* until one of them succeeds. When that happens, the remaining tasks will not run.
* */
class MultipleOptionsTask : public SequentialTask
{
Q_OBJECT
public:
explicit MultipleOptionsTask(QObject *parent = nullptr, const QString& task_name = "");
virtual ~MultipleOptionsTask() = default;
private
slots:
void startNext() override;
void subTaskFailed(const QString &msg) override;
};

View File

@ -20,17 +20,17 @@ public:
void addTask(Task::Ptr task); void addTask(Task::Ptr task);
protected slots:
void executeTask() override;
public slots: public slots:
bool abort() override; bool abort() override;
private protected
slots: slots:
void startNext(); void executeTask() override;
void subTaskFailed(const QString &msg);
void subTaskStatus(const QString &msg); virtual void startNext();
void subTaskProgress(qint64 current, qint64 total); virtual void subTaskFailed(const QString &msg);
virtual void subTaskStatus(const QString &msg);
virtual void subTaskProgress(qint64 current, qint64 total);
protected: protected:
void setStepStatus(QString status) { m_step_status = status; emit stepStatus(status); }; void setStepStatus(QString status) { m_step_status = status; emit stepStatus(status); };