[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
This commit is contained in:
95
application/state/sftp/transferPauseLatch.ts
Normal file
95
application/state/sftp/transferPauseLatch.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Process-wide pause latches for SFTP transfers.
|
||||
*
|
||||
* Must outlive any React owner (SFTP panel / vault page). Directory walks and
|
||||
* stream workers wait on these latches; the global transfer center sets them
|
||||
* on Pause and clears them on Resume whether or not a panel is mounted.
|
||||
*/
|
||||
|
||||
const pausedIds = new Set<string>();
|
||||
const barriers = new Map<string, { promise: Promise<void>; resolve: () => void }>();
|
||||
// A completed child's history row can disappear while its worker still waits
|
||||
// for the folder to resume. Keep the paused tree independent of UI history.
|
||||
const pausedChildren = new Map<string, Set<string>>();
|
||||
|
||||
function ensureBarrier(taskId: string): { promise: Promise<void>; resolve: () => void } {
|
||||
let barrier = barriers.get(taskId);
|
||||
if (barrier) return barrier;
|
||||
let resolve!: () => void;
|
||||
const promise = new Promise<void>((r) => {
|
||||
resolve = r;
|
||||
});
|
||||
barrier = { promise, resolve };
|
||||
barriers.set(taskId, barrier);
|
||||
return barrier;
|
||||
}
|
||||
|
||||
export function isTransferPauseLatched(taskId: string): boolean {
|
||||
return pausedIds.has(taskId);
|
||||
}
|
||||
|
||||
export function isTransferOrRootPauseLatched(rootTaskId: string, taskId?: string): boolean {
|
||||
return pausedIds.has(rootTaskId) || (!!taskId && pausedIds.has(taskId));
|
||||
}
|
||||
|
||||
/** Latch pause for a task id. Idempotent; creates a waiter barrier. */
|
||||
export function latchTransferPause(taskId: string): void {
|
||||
pausedIds.add(taskId);
|
||||
ensureBarrier(taskId);
|
||||
}
|
||||
|
||||
/** Release pause and wake every waiter. Idempotent. */
|
||||
export function releaseTransferPause(taskId: string): void {
|
||||
pausedIds.delete(taskId);
|
||||
const barrier = barriers.get(taskId);
|
||||
if (!barrier) return;
|
||||
barriers.delete(taskId);
|
||||
barrier.resolve();
|
||||
}
|
||||
|
||||
export function releaseTransferPauseTree(rootTaskId: string, childIds: readonly string[] = []): void {
|
||||
const children = new Set([...childIds, ...(pausedChildren.get(rootTaskId) ?? [])]);
|
||||
pausedChildren.delete(rootTaskId);
|
||||
releaseTransferPause(rootTaskId);
|
||||
for (const id of children) releaseTransferPause(id);
|
||||
}
|
||||
|
||||
export function latchTransferPauseTree(rootTaskId: string, childIds: readonly string[] = []): void {
|
||||
if (childIds.length > 0) {
|
||||
const children = pausedChildren.get(rootTaskId) ?? new Set<string>();
|
||||
for (const id of childIds) children.add(id);
|
||||
pausedChildren.set(rootTaskId, children);
|
||||
}
|
||||
latchTransferPause(rootTaskId);
|
||||
for (const id of childIds) latchTransferPause(id);
|
||||
}
|
||||
|
||||
export async function waitUntilTransferPauseReleased(taskId: string): Promise<void> {
|
||||
while (pausedIds.has(taskId)) {
|
||||
const barrier = ensureBarrier(taskId);
|
||||
await barrier.promise;
|
||||
}
|
||||
}
|
||||
|
||||
export async function waitWhileTransferOrRootPaused(
|
||||
rootTaskId: string,
|
||||
taskId?: string,
|
||||
): Promise<void> {
|
||||
while (isTransferOrRootPauseLatched(rootTaskId, taskId)) {
|
||||
const latchId = pausedIds.has(rootTaskId) ? rootTaskId : (taskId as string);
|
||||
await waitUntilTransferPauseReleased(latchId);
|
||||
}
|
||||
}
|
||||
|
||||
/** Test helper — clear all latches between cases. */
|
||||
export function resetTransferPauseLatchesForTests(): void {
|
||||
const ids = [...pausedIds];
|
||||
for (const id of ids) releaseTransferPause(id);
|
||||
pausedIds.clear();
|
||||
barriers.clear();
|
||||
pausedChildren.clear();
|
||||
}
|
||||
|
||||
export function listTransferPauseLatchesForTests(): string[] {
|
||||
return [...pausedIds].sort();
|
||||
}
|
||||
Reference in New Issue
Block a user