(executor: CommandExecutor)
| 602 | continue; |
| 603 | } |
| 604 | const mtimeSeconds = Number.parseInt(statResult.stdout.trim(), 10); |
| 605 | if (!Number.isFinite(mtimeSeconds)) { |
| 606 | logger |
| 607 | .withFields({ candidateSessionId }) |
| 608 | .info('Skipping session: could not parse directory mtime'); |
| 609 | skipped++; |
| 610 | continue; |
| 611 | } |
| 612 | const ageSeconds = nowSeconds - mtimeSeconds; |
| 613 | if (ageSeconds < STALE_DIR_MIN_AGE_SECONDS) { |
| 614 | logger |
| 615 | .withFields({ candidateSessionId, ageSeconds }) |
| 616 | .info('Skipping session: directory too recent'); |
| 617 | skipped++; |
| 618 | continue; |
| 619 | } |
| 620 | |
| 621 | if (isWrapperLiveInProcessesOrContainers(processes, wrapperContainers, candidateSessionId)) { |
| 622 | logger.withFields({ candidateSessionId }).info('Skipping session: wrapper is running'); |
| 623 | skipped++; |
| 624 | continue; |
| 625 | } |
| 626 | |
| 627 | const sessionHome = getSessionHomePath(candidateSessionId); |
| 628 | logger |
| 629 | .withFields({ candidateSessionId, workspacePath, sessionHome }) |
| 630 | .info('Removing stale session directories'); |
| 631 | |
| 632 | const cleanup = await cleanupWorkspaceBestEffort(sandbox, workspacePath, sessionHome); |
| 633 | if (cleanup.filesystemUnusableCause !== undefined) { |
| 634 | throwIfSandboxFilesystemUnusable( |
| 635 | 'Stale workspace cleanup', |
| 636 | cleanup.filesystemUnusableCause |
| 637 | ); |
| 638 | } |
| 639 | if (cleanup.cleaned) cleaned++; |
| 640 | else skipped++; |
| 641 | } catch (error) { |
| 642 | if (error instanceof SandboxCapacityInspectionError) throw error; |
| 643 | throwIfSandboxFilesystemUnusable('Stale workspace cleanup', error); |
| 644 | skipped++; |
| 645 | logger |
| 646 | .withFields({ |
| 647 | candidateSessionId, |
| 648 | error: error instanceof Error ? error.message : String(error), |
| 649 | }) |
| 650 | .warn('Error while cleaning up stale session, continuing'); |
| 651 | } |
| 652 | } |
| 653 | |
| 654 | const result = { cleaned, skipped } satisfies StaleWorkspaceCleanupResult; |
| 655 | logger.withFields(result).info('Stale workspace cleanup complete'); |
| 656 | return result; |
| 657 | } |
| 658 | |
| 659 | export type GitAuthorConfig = { |
| 660 | name: string; |
| 661 | email: string; |
no test coverage detected