|
@@ -863,14 +863,51 @@ namespace ClankerSaddle.Services {
|
|
|
try {
|
|
try {
|
|
|
var status = yield request_saddle_json(((!)saddle).host, "GET", "/status", null);
|
|
var status = yield request_saddle_json(((!)saddle).host, "GET", "/status", null);
|
|
|
string state = status.has_member("state") ? status.get_string_member_with_default("state", "") : "";
|
|
string state = status.has_member("state") ? status.get_string_member_with_default("state", "") : "";
|
|
|
- ((!)saddle).status = state == "idle" ? "idle" : "busy";
|
|
|
|
|
|
|
+ if (state == "working") {
|
|
|
|
|
+ // Reconcile with the web's own records: busy only when
|
|
|
|
|
+ // a live session truly holds this saddle.
|
|
|
|
|
+ var session = yield open_session_on_saddle(id);
|
|
|
|
|
+ ((!)saddle).status = "busy";
|
|
|
|
|
+ ((!)saddle).current_task_id = session != null ? ((!)session).task_id : 0;
|
|
|
|
|
+ ((!)saddle).allocated_at = session != null ? ((!)session).started_at : null;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // Idle AND the parked states (blocked/suspended, plus
|
|
|
|
|
+ // terminal and unknown states): the workspace is
|
|
|
|
|
+ // parked, so the saddle is logically free — marking it
|
|
|
|
|
+ // busy here used to wedge assignment against a daemon
|
|
|
|
|
+ // that would never poll.
|
|
|
|
|
+ ((!)saddle).status = "idle";
|
|
|
|
|
+ ((!)saddle).current_task_id = 0;
|
|
|
|
|
+ ((!)saddle).allocated_at = null;
|
|
|
|
|
+ }
|
|
|
} catch (Error e) {
|
|
} catch (Error e) {
|
|
|
((!)saddle).status = "offline";
|
|
((!)saddle).status = "offline";
|
|
|
|
|
+ ((!)saddle).current_task_id = 0;
|
|
|
|
|
+ ((!)saddle).allocated_at = null;
|
|
|
}
|
|
}
|
|
|
yield db.update_async<Saddle>((!)saddle);
|
|
yield db.update_async<Saddle>((!)saddle);
|
|
|
yield pulse.bump(0, "saddle status refreshed");
|
|
yield pulse.bump(0, "saddle status refreshed");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * The saddle's open (live or parked) session, or null — the
|
|
|
|
|
+ * reconciliation source for whether a daemon is genuinely
|
|
|
|
|
+ * running one of our tasks.
|
|
|
|
|
+ */
|
|
|
|
|
+ private async ClankerSaddle.Data.Session? open_session_on_saddle(int64 saddle_id) throws Error {
|
|
|
|
|
+ var sessions = yield db.query<ClankerSaddle.Data.Session>()
|
|
|
|
|
+ .where(expr("saddle_id == $0", elem<int64?>(saddle_id)))
|
|
|
|
|
+ .order_by(expr("id"))
|
|
|
|
|
+ .materialise_async();
|
|
|
|
|
+ ClankerSaddle.Data.Session? newest_open = null;
|
|
|
|
|
+ foreach (var session in sessions) {
|
|
|
|
|
+ if (session.ended_at == null) {
|
|
|
|
|
+ newest_open = session;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return newest_open;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* Answered blocks of the saddle's current task not yet handed over
|
|
* Answered blocks of the saddle's current task not yet handed over
|
|
|
* the poll endpoint; marks them delivered.
|
|
* the poll endpoint; marks them delivered.
|