update mission cancel
Some checks failed
Test / test (push) Has been cancelled

This commit is contained in:
2026-06-15 10:30:00 +07:00
parent 6cc51a35c4
commit 4b372100eb
13 changed files with 922 additions and 134 deletions

View File

@@ -12,6 +12,12 @@ namespace lm {
namespace {
class MissionCancelled : public std::runtime_error
{
public:
MissionCancelled() : std::runtime_error("mission cancelled") {}
};
std::string paramValue(const std::string& action_id,
const nlohmann::json& params,
const std::string& key,
@@ -319,6 +325,30 @@ bool MissionQueue::resume(std::string& err)
return true;
}
bool MissionQueue::cancel(std::string& err)
{
std::lock_guard<std::recursive_mutex> lock(mu_);
const std::string state = runner_.value("state", "idle");
if (state != "running" && state != "paused")
{
err = "no mission is running";
return false;
}
if (cancel_)
{
err = "cancel already in progress";
return false;
}
cancel_ = true;
paused_ = false;
runner_["paused"] = false;
runner_["message"] = "Đang hủy mission…";
runner_["updated_at"] = IdUtil::nowIso8601();
saveUnlocked();
wake_ = true;
return true;
}
void MissionQueue::workerLoop()
{
while (!stop_)
@@ -382,14 +412,17 @@ void MissionQueue::workerLoop()
void MissionQueue::runMissionActions(nlohmann::json& entry)
{
cancel_ = false;
nlohmann::json log = nlohmann::json::array();
try
{
nlohmann::json log = nlohmann::json::array();
const auto& mission = entry["mission"];
const auto& parameters = entry["parameters"];
const auto& actions =
mission.contains("actions") && mission["actions"].is_array() ? mission["actions"] : nlohmann::json::array();
executeActionsUnlocked(actions, parameters, log, 0);
if (cancel_)
throw MissionCancelled();
entry["log"] = log;
entry["status"] = "completed";
entry["finished_at"] = IdUtil::nowIso8601();
@@ -399,6 +432,18 @@ void MissionQueue::runMissionActions(nlohmann::json& entry)
saveUnlocked();
}
}
catch (const MissionCancelled&)
{
log.push_back({{"ts", IdUtil::nowIso8601()}, {"level", "warn"}, {"message", "Mission hủy bởi operator"}});
entry["log"] = log;
entry["status"] = "cancelled";
entry["finished_at"] = IdUtil::nowIso8601();
{
std::lock_guard<std::recursive_mutex> lock(mu_);
setRunnerState("idle", "Đã hủy: " + entry.value("mission_name", "Mission"));
saveUnlocked();
}
}
catch (...)
{
entry["status"] = "failed";
@@ -409,6 +454,7 @@ void MissionQueue::runMissionActions(nlohmann::json& entry)
saveUnlocked();
}
}
cancel_ = false;
}
MissionQueue::LoopControl MissionQueue::executeActionsUnlocked(const nlohmann::json& actions,
@@ -423,10 +469,12 @@ MissionQueue::LoopControl MissionQueue::executeActionsUnlocked(const nlohmann::j
{
if (!action.is_object())
continue;
while (paused_ && !stop_)
while (paused_ && !stop_ && !cancel_)
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if (stop_)
return LoopControl::None;
if (cancel_)
throw MissionCancelled();
const std::string action_id = action.value("id", "");
const std::string kind = action.value("kind", "action");
@@ -478,7 +526,7 @@ MissionQueue::LoopControl MissionQueue::executeActionsUnlocked(const nlohmann::j
const auto& children =
action.contains("children") && action["children"].is_array() ? action["children"] : nlohmann::json::array();
const int iterations = mode == "endless" ? 10000 : std::max(1, count);
for (int i = 0; i < iterations && !stop_; ++i)
for (int i = 0; i < iterations && !stop_ && !cancel_; ++i)
{
if (mode == "endless" && i == 0)
{
@@ -497,6 +545,8 @@ MissionQueue::LoopControl MissionQueue::executeActionsUnlocked(const nlohmann::j
break;
if (ctrl == LoopControl::Continue)
continue;
if (cancel_)
throw MissionCancelled();
}
continue;
}
@@ -506,6 +556,8 @@ MissionQueue::LoopControl MissionQueue::executeActionsUnlocked(const nlohmann::j
const int ms = static_cast<int>(paramNumber(params, "seconds", 1) * 1000);
log.push_back({{"ts", IdUtil::nowIso8601()}, {"level", "info"}, {"message", "Wait " + std::to_string(ms) + "ms"}});
sleepMs(ms);
if (cancel_)
throw MissionCancelled();
continue;
}
@@ -516,6 +568,8 @@ MissionQueue::LoopControl MissionQueue::executeActionsUnlocked(const nlohmann::j
{"level", "info"},
{"message", label + "" + (pos.empty() ? "?" : pos)}});
sleepMs(1200);
if (cancel_)
throw MissionCancelled();
continue;
}
@@ -526,6 +580,8 @@ MissionQueue::LoopControl MissionQueue::executeActionsUnlocked(const nlohmann::j
{"level", "info"},
{"message", label + "" + (marker.empty() ? "?" : marker)}});
sleepMs(1200);
if (cancel_)
throw MissionCancelled();
continue;
}
@@ -534,6 +590,8 @@ MissionQueue::LoopControl MissionQueue::executeActionsUnlocked(const nlohmann::j
const std::string message = params.value("message", "Mission step");
log.push_back({{"ts", IdUtil::nowIso8601()}, {"level", "user"}, {"message", message}});
sleepMs(200);
if (cancel_)
throw MissionCancelled();
continue;
}
@@ -541,12 +599,16 @@ MissionQueue::LoopControl MissionQueue::executeActionsUnlocked(const nlohmann::j
{
log.push_back({{"ts", IdUtil::nowIso8601()}, {"level", "warn"}, {"message", "Pause (simulated)"}});
sleepMs(500);
if (cancel_)
throw MissionCancelled();
continue;
}
log.push_back(
{{"ts", IdUtil::nowIso8601()}, {"level", "info"}, {"message", label + " (" + type + ") simulated"}});
sleepMs(400);
if (cancel_)
throw MissionCancelled();
}
return LoopControl::None;
}
@@ -556,9 +618,9 @@ void MissionQueue::sleepMs(int ms)
if (ms <= 0)
return;
const int step = 100;
for (int elapsed = 0; elapsed < ms && !stop_; elapsed += step)
for (int elapsed = 0; elapsed < ms && !stop_ && !cancel_; elapsed += step)
{
while (paused_ && !stop_)
while (paused_ && !stop_ && !cancel_)
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(std::chrono::milliseconds(std::min(step, ms - elapsed)));
}