@@ -6,6 +6,16 @@ import { type Logger } from "../logging/logger";
66
77import * as downloadProgress from "./downloadProgress" ;
88
9+ /**
10+ * Timeout to detect stale lock files and take over from stuck processes.
11+ * This value is intentionally small so we can quickly takeover.
12+ */
13+ const STALE_TIMEOUT_MS = 15000 ;
14+
15+ const LOCK_POLL_INTERVAL_MS = 500 ;
16+
17+ type LockRelease = ( ) => Promise < void > ;
18+
919/**
1020 * Manages file locking for binary downloads to coordinate between multiple
1121 * VS Code windows downloading the same binary.
@@ -23,7 +33,7 @@ export class BinaryLock {
2333 async acquireLockOrWait (
2434 binPath : string ,
2535 progressLogPath : string ,
26- ) : Promise < { release : ( ) => Promise < void > ; waited : boolean } > {
36+ ) : Promise < { release : LockRelease ; waited : boolean } > {
2737 const release = await this . safeAcquireLock ( binPath ) ;
2838 if ( release ) {
2939 return { release, waited : false } ;
@@ -43,12 +53,10 @@ export class BinaryLock {
4353 * Attempt to acquire a lock on the binary file.
4454 * Returns the release function if successful, null if lock is already held.
4555 */
46- private async safeAcquireLock (
47- path : string ,
48- ) : Promise < ( ( ) => Promise < void > ) | null > {
56+ private async safeAcquireLock ( path : string ) : Promise < LockRelease | null > {
4957 try {
5058 const release = await lockfile . lock ( path , {
51- stale : downloadProgress . STALE_TIMEOUT_MS ,
59+ stale : STALE_TIMEOUT_MS ,
5260 retries : 0 ,
5361 realpath : false ,
5462 } ) ;
@@ -69,44 +77,50 @@ export class BinaryLock {
6977 private async monitorDownloadProgress (
7078 binPath : string ,
7179 progressLogPath : string ,
72- ) : Promise < ( ) => Promise < void > > {
80+ ) : Promise < LockRelease > {
7381 return await this . vscodeProposed . window . withProgress (
7482 {
7583 location : vscode . ProgressLocation . Notification ,
7684 title : "Another window is downloading the Coder CLI binary" ,
7785 cancellable : false ,
7886 } ,
7987 async ( progress ) => {
80- return new Promise < ( ) => Promise < void > > ( ( resolve , reject ) => {
81- const interval = setInterval ( async ( ) => {
88+ return new Promise < LockRelease > ( ( resolve , reject ) => {
89+ const poll = async ( ) => {
8290 try {
83- const currentProgress =
84- await downloadProgress . readProgress ( progressLogPath ) ;
85- if ( currentProgress ) {
86- const totalBytesPretty =
87- currentProgress . totalBytes === null
88- ? "unknown"
89- : prettyBytes ( currentProgress . totalBytes ) ;
90- const message =
91- currentProgress . status === "verifying"
92- ? "Verifying signature..."
93- : `${ prettyBytes ( currentProgress . bytesDownloaded ) } / ${ totalBytesPretty } ` ;
94- progress . report ( { message } ) ;
95- }
96-
91+ await this . updateProgressMonitor ( progressLogPath , progress ) ;
9792 const release = await this . safeAcquireLock ( binPath ) ;
9893 if ( release ) {
99- clearInterval ( interval ) ;
100- this . output . debug ( "Download completed by another process" ) ;
10194 return resolve ( release ) ;
10295 }
96+ // Schedule next poll only after current one completes
97+ setTimeout ( poll , LOCK_POLL_INTERVAL_MS ) ;
10398 } catch ( error ) {
104- clearInterval ( interval ) ;
10599 reject ( error ) ;
106100 }
107- } , 500 ) ;
101+ } ;
102+ poll ( ) . catch ( ( error ) => reject ( error ) ) ;
108103 } ) ;
109104 } ,
110105 ) ;
111106 }
107+
108+ private async updateProgressMonitor (
109+ progressLogPath : string ,
110+ progress : vscode . Progress < { message ?: string } > ,
111+ ) : Promise < void > {
112+ const currentProgress =
113+ await downloadProgress . readProgress ( progressLogPath ) ;
114+ if ( currentProgress ) {
115+ const totalBytesPretty =
116+ currentProgress . totalBytes === null
117+ ? "unknown"
118+ : prettyBytes ( currentProgress . totalBytes ) ;
119+ const message =
120+ currentProgress . status === "verifying"
121+ ? "Verifying signature..."
122+ : `${ prettyBytes ( currentProgress . bytesDownloaded ) } / ${ totalBytesPretty } ` ;
123+ progress . report ( { message } ) ;
124+ }
125+ }
112126}
0 commit comments