@@ -58,9 +58,7 @@ export class DiskBasedResultStorage implements AccuracyResultStorage {
5858
5959 async updateRunStatus ( commitSHA : string , runId : string , status : AccuracyRunStatuses ) : Promise < void > {
6060 const resultFilePath = this . getAccuracyResultFilePath ( commitSHA , runId ) ;
61- let releaseLock : ( ( ) => Promise < void > ) | undefined ;
62- try {
63- releaseLock = await lock ( resultFilePath , { retries : 10 } ) ;
61+ await this . withFileLock ( resultFilePath , async ( ) => {
6462 const accuracyResult = await this . getAccuracyResult ( commitSHA , runId , false ) ;
6563 if ( ! accuracyResult ) {
6664 throw new Error ( "Results not found!" ) ;
@@ -78,23 +76,15 @@ export class DiskBasedResultStorage implements AccuracyResultStorage {
7876 ) ,
7977 { encoding : "utf8" }
8078 ) ;
81- } catch ( error ) {
82- console . warn (
83- `Could not update run status to ${ status } for commit - ${ commitSHA } , runId - ${ runId } .` ,
84- error
85- ) ;
86- throw error ;
87- } finally {
88- await releaseLock ?.( ) ;
89- }
79+ } ) ;
9080
9181 // This bit is important to mark the current run as the latest run for a
9282 // commit so that we can use that during baseline comparison.
9383 if ( status === AccuracyRunStatus . Done ) {
94- await this . atomicUpdateLink (
95- this . getAccuracyResultFilePath ( commitSHA , runId ) ,
96- this . getLatestResultFilePath ( commitSHA )
97- ) ;
84+ const latestResultFilePath = this . getLatestResultFilePath ( commitSHA ) ;
85+ await this . withFileLock ( latestResultFilePath , async ( ) => {
86+ await fs . link ( resultFilePath , latestResultFilePath ) ;
87+ } ) ;
9888 }
9989 }
10090
@@ -134,50 +124,36 @@ export class DiskBasedResultStorage implements AccuracyResultStorage {
134124 return ;
135125 }
136126
137- let releaseLock : ( ( ) => Promise < void > ) | undefined ;
138- try {
139- releaseLock = await lock ( resultFilePath , { retries : 10 } ) ;
140- const accuracyResult = await this . getAccuracyResult ( commitSHA , runId , false ) ;
127+ await this . withFileLock ( resultFilePath , async ( ) => {
128+ let accuracyResult = await this . getAccuracyResult ( commitSHA , runId , false ) ;
141129 if ( ! accuracyResult ) {
142130 throw new Error ( "Expected at-least initial accuracy result to be present" ) ;
143131 }
144132
145133 const existingPromptIdx = accuracyResult . promptResults . findIndex ( ( result ) => result . prompt === prompt ) ;
146134 const promptResult = accuracyResult . promptResults [ existingPromptIdx ] ;
147- if ( ! promptResult ) {
148- return await fs . writeFile (
149- resultFilePath ,
150- JSON . stringify (
135+ if ( promptResult ) {
136+ accuracyResult . promptResults . splice ( existingPromptIdx , 1 , {
137+ prompt : promptResult . prompt ,
138+ expectedToolCalls : promptResult . expectedToolCalls ,
139+ modelResponses : [ ...promptResult . modelResponses , modelResponse ] ,
140+ } ) ;
141+ } else {
142+ accuracyResult = {
143+ ...accuracyResult ,
144+ promptResults : [
145+ ...accuracyResult . promptResults ,
151146 {
152- ...accuracyResult ,
153- promptResults : [
154- ...accuracyResult . promptResults ,
155- {
156- prompt,
157- expectedToolCalls,
158- modelResponses : [ modelResponse ] ,
159- } ,
160- ] ,
147+ prompt,
148+ expectedToolCalls,
149+ modelResponses : [ modelResponse ] ,
161150 } ,
162- null ,
163- 2
164- )
165- ) ;
151+ ] ,
152+ } ;
166153 }
167154
168- accuracyResult . promptResults . splice ( existingPromptIdx , 1 , {
169- prompt : promptResult . prompt ,
170- expectedToolCalls : promptResult . expectedToolCalls ,
171- modelResponses : [ ...promptResult . modelResponses , modelResponse ] ,
172- } ) ;
173-
174- return await fs . writeFile ( resultFilePath , JSON . stringify ( accuracyResult , null , 2 ) ) ;
175- } catch ( error ) {
176- console . warn ( `Could not save model response for commit - ${ commitSHA } , runId - ${ runId } .` , error ) ;
177- throw error ;
178- } finally {
179- await releaseLock ?.( ) ;
180- }
155+ await fs . writeFile ( resultFilePath , JSON . stringify ( accuracyResult , null , 2 ) ) ;
156+ } ) ;
181157 }
182158
183159 close ( ) : Promise < void > {
@@ -206,20 +182,16 @@ export class DiskBasedResultStorage implements AccuracyResultStorage {
206182 }
207183 }
208184
209- private async atomicUpdateLink ( filePath : string , linkPath : string ) {
210- for ( let attempt = 0 ; attempt < 10 ; attempt ++ ) {
211- try {
212- const tempLinkPath = `${ linkPath } ~${ Date . now ( ) } ` ;
213- await fs . link ( filePath , tempLinkPath ) ;
214- await fs . rename ( tempLinkPath , linkPath ) ;
215- return ;
216- } catch ( error ) {
217- if ( attempt < 10 ) {
218- await this . waitFor ( 100 + Math . random ( ) * 200 ) ;
219- } else {
220- throw error ;
221- }
222- }
185+ private async withFileLock ( filePath : string , callback : ( ) => Promise < void > ) : Promise < void > {
186+ let releaseLock : ( ( ) => Promise < void > ) | undefined ;
187+ try {
188+ releaseLock = await lock ( filePath , { retries : 10 } ) ;
189+ await callback ( ) ;
190+ } catch ( error ) {
191+ console . warn ( `Could not acquire lock for file - ${ filePath } .` , error ) ;
192+ throw error ;
193+ } finally {
194+ await releaseLock ?.( ) ;
223195 }
224196 }
225197
@@ -230,8 +202,4 @@ export class DiskBasedResultStorage implements AccuracyResultStorage {
230202 private getLatestResultFilePath ( commitSHA : string ) : string {
231203 return path . join ( ACCURACY_RESULTS_DIR , commitSHA , `${ LATEST_ACCURACY_RUN_NAME } .json` ) ;
232204 }
233-
234- private waitFor ( ms : number ) {
235- return new Promise ( ( resolve ) => setTimeout ( resolve , ms ) ) ;
236- }
237205}
0 commit comments