This commit is contained in:
@@ -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)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user