fix(watcher): fix TickCount wrap and resume retry on API failure
- Use 32-bit Environment.TickCount with unchecked uint arithmetic so GetIdleTime stays correct after the ~49.7 day uint wrap boundary - Only clear _pausedTaskId after successful resume, not before the API call - Add retry path: if resume failed, retry on next poll cycle while user is still active Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -29,6 +29,7 @@ internal static partial class NativeMethods
|
||||
var info = new LASTINPUTINFO { cbSize = (uint)Marshal.SizeOf<LASTINPUTINFO>() };
|
||||
if (!GetLastInputInfo(ref info))
|
||||
return TimeSpan.Zero;
|
||||
return TimeSpan.FromMilliseconds(Environment.TickCount64 - info.dwTime);
|
||||
// Use 32-bit TickCount so both values wrap at the same boundary as dwTime (uint)
|
||||
return TimeSpan.FromMilliseconds(unchecked((uint)Environment.TickCount - info.dwTime));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,12 @@ public class Worker(
|
||||
|
||||
// Idle detection
|
||||
var idleTime = NativeMethods.GetIdleTime();
|
||||
if (!_isIdle && idleTime.TotalMilliseconds >= config.IdleTimeoutMs)
|
||||
if (!_isIdle && _pausedTaskId is not null && idleTime.TotalMilliseconds < config.IdleTimeoutMs)
|
||||
{
|
||||
// Retry resume from a previous failed attempt
|
||||
await ResumeIdlePausedTaskAsync(ct: stoppingToken);
|
||||
}
|
||||
else if (!_isIdle && idleTime.TotalMilliseconds >= config.IdleTimeoutMs)
|
||||
{
|
||||
_isIdle = true;
|
||||
logger.LogInformation("User idle for {IdleTime}, pausing active task", idleTime);
|
||||
@@ -167,7 +172,6 @@ public class Worker(
|
||||
return;
|
||||
|
||||
var taskId = _pausedTaskId.Value;
|
||||
_pausedTaskId = null;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -180,6 +184,7 @@ public class Worker(
|
||||
if (response?.Data is null || response.Data.Status != "Paused")
|
||||
{
|
||||
logger.LogDebug("Task {TaskId} is no longer paused, skipping auto-resume", taskId);
|
||||
_pausedTaskId = null;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -189,13 +194,18 @@ public class Worker(
|
||||
new { note = "Auto-resumed: user returned" }, ct);
|
||||
|
||||
if (resumeResponse.IsSuccessStatusCode)
|
||||
{
|
||||
logger.LogInformation("Auto-resumed task {TaskId}", taskId);
|
||||
_pausedTaskId = null;
|
||||
}
|
||||
else
|
||||
logger.LogWarning("Failed to resume task {TaskId}: {Status}", taskId, resumeResponse.StatusCode);
|
||||
{
|
||||
logger.LogWarning("Failed to resume task {TaskId}: {Status}, will retry", taskId, resumeResponse.StatusCode);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogWarning(ex, "Failed to resume task {TaskId} after idle", taskId);
|
||||
logger.LogWarning(ex, "Failed to resume task {TaskId} after idle, will retry", taskId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user