| 1278 | } |
| 1279 | |
| 1280 | void mitk::nnInteractiveTool::Heartbeat() |
| 1281 | { |
| 1282 | if (!m_Impl->Remote || !this->IsSessionRunning()) |
| 1283 | return; |
| 1284 | |
| 1285 | auto pythonContext = m_Impl->GetPythonContext(); |
| 1286 | bool expired = false; |
| 1287 | |
| 1288 | try |
| 1289 | { |
| 1290 | // Mirror the library's own _heartbeat_loop tolerance: only a definitive |
| 1291 | // SessionExpiredError means the lease is gone. Everything else is non-fatal, |
| 1292 | // matching the library, which keeps the session alive and surfaces a real |
| 1293 | // expiry on the user's next action: a transient httpx error, a |
| 1294 | // ServerAtCapacityError (a 503 on a beat), and a malformed response |
| 1295 | // (json.JSONDecodeError) all just let the next beat retry. We classify inside |
| 1296 | // Python and read back a flag, so a transient blip never reaches the broad |
| 1297 | // remote guard (WrapInRemoteGuard) that would tear the session down. |
| 1298 | // SessionExpiredError was imported by ConstructRemoteSession() and persists in |
| 1299 | // the shared dictionary for the session's lifetime. |
| 1300 | pythonContext->Execute( |
| 1301 | "try:\n" |
| 1302 | " session.heartbeat()\n" |
| 1303 | " nni_hb_expired = False\n" |
| 1304 | "except SessionExpiredError:\n" |
| 1305 | " nni_hb_expired = True\n" |
| 1306 | "except Exception:\n" |
| 1307 | " nni_hb_expired = False\n"); |
| 1308 | |
| 1309 | expired = pythonContext->GetVariableAsBool("nni_hb_expired").value_or(false); |
| 1310 | pythonContext->Execute("del nni_hb_expired\n"); |
| 1311 | } |
| 1312 | catch (const Exception& e) |
| 1313 | { |
| 1314 | // Heartbeat() runs from a Qt timer slot, so never let an exception escape. |
| 1315 | MITK_WARN << "nnInteractive: heartbeat failed unexpectedly (ignored): " << e.GetDescription(); |
| 1316 | return; |
| 1317 | } |
| 1318 | |
| 1319 | if (expired) |
| 1320 | { |
| 1321 | // The lease is gone server-side. Signal the GUI, which tears the dead |
| 1322 | // session down on the next event-loop tick (same deferred path used for a |
| 1323 | // connection loss detected mid-interaction). |
| 1324 | this->SessionExpiredEvent.Send(); |
| 1325 | } |
| 1326 | } |
| 1327 | |
| 1328 | mitk::nnInteractiveTool::SupportedInteractions mitk::nnInteractiveTool::GetSupportedInteractions() const |
| 1329 | { |
no test coverage detected