@@ -58,9 +58,7 @@ export class DiskBasedResultStorage implements AccuracyResultStorage {
58
58
59
59
async updateRunStatus ( commitSHA : string , runId : string , status : AccuracyRunStatuses ) : Promise < void > {
60
60
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 ( ) => {
64
62
const accuracyResult = await this . getAccuracyResult ( commitSHA , runId , false ) ;
65
63
if ( ! accuracyResult ) {
66
64
throw new Error ( "Results not found!" ) ;
@@ -78,23 +76,16 @@ export class DiskBasedResultStorage implements AccuracyResultStorage {
78
76
) ,
79
77
{ encoding : "utf8" }
80
78
) ;
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
+ } ) ;
90
80
91
81
// This bit is important to mark the current run as the latest run for a
92
82
// commit so that we can use that during baseline comparison.
93
83
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 . unlink ( latestResultFilePath ) ;
87
+ await fs . link ( resultFilePath , latestResultFilePath ) ;
88
+ } ) ;
98
89
}
99
90
}
100
91
@@ -134,50 +125,36 @@ export class DiskBasedResultStorage implements AccuracyResultStorage {
134
125
return ;
135
126
}
136
127
137
- let releaseLock : ( ( ) => Promise < void > ) | undefined ;
138
- try {
139
- releaseLock = await lock ( resultFilePath , { retries : 10 } ) ;
140
- const accuracyResult = await this . getAccuracyResult ( commitSHA , runId , false ) ;
128
+ await this . withFileLock ( resultFilePath , async ( ) => {
129
+ let accuracyResult = await this . getAccuracyResult ( commitSHA , runId , false ) ;
141
130
if ( ! accuracyResult ) {
142
131
throw new Error ( "Expected at-least initial accuracy result to be present" ) ;
143
132
}
144
133
145
134
const existingPromptIdx = accuracyResult . promptResults . findIndex ( ( result ) => result . prompt === prompt ) ;
146
135
const promptResult = accuracyResult . promptResults [ existingPromptIdx ] ;
147
- if ( ! promptResult ) {
148
- return await fs . writeFile (
149
- resultFilePath ,
150
- JSON . stringify (
136
+ if ( promptResult ) {
137
+ accuracyResult . promptResults . splice ( existingPromptIdx , 1 , {
138
+ prompt : promptResult . prompt ,
139
+ expectedToolCalls : promptResult . expectedToolCalls ,
140
+ modelResponses : [ ...promptResult . modelResponses , modelResponse ] ,
141
+ } ) ;
142
+ } else {
143
+ accuracyResult = {
144
+ ...accuracyResult ,
145
+ promptResults : [
146
+ ...accuracyResult . promptResults ,
151
147
{
152
- ...accuracyResult ,
153
- promptResults : [
154
- ...accuracyResult . promptResults ,
155
- {
156
- prompt,
157
- expectedToolCalls,
158
- modelResponses : [ modelResponse ] ,
159
- } ,
160
- ] ,
148
+ prompt,
149
+ expectedToolCalls,
150
+ modelResponses : [ modelResponse ] ,
161
151
} ,
162
- null ,
163
- 2
164
- )
165
- ) ;
152
+ ] ,
153
+ } ;
166
154
}
167
155
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
- }
156
+ await fs . writeFile ( resultFilePath , JSON . stringify ( accuracyResult , null , 2 ) ) ;
157
+ } ) ;
181
158
}
182
159
183
160
close ( ) : Promise < void > {
@@ -206,20 +183,16 @@ export class DiskBasedResultStorage implements AccuracyResultStorage {
206
183
}
207
184
}
208
185
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
- }
186
+ private async withFileLock ( filePath : string , callback : ( ) => Promise < void > ) : Promise < void > {
187
+ let releaseLock : ( ( ) => Promise < void > ) | undefined ;
188
+ try {
189
+ releaseLock = await lock ( filePath , { retries : 10 } ) ;
190
+ await callback ( ) ;
191
+ } catch ( error ) {
192
+ console . warn ( `Could not acquire lock for file - ${ filePath } .` , error ) ;
193
+ throw error ;
194
+ } finally {
195
+ await releaseLock ?.( ) ;
223
196
}
224
197
}
225
198
@@ -230,8 +203,4 @@ export class DiskBasedResultStorage implements AccuracyResultStorage {
230
203
private getLatestResultFilePath ( commitSHA : string ) : string {
231
204
return path . join ( ACCURACY_RESULTS_DIR , commitSHA , `${ LATEST_ACCURACY_RUN_NAME } .json` ) ;
232
205
}
233
-
234
- private waitFor ( ms : number ) {
235
- return new Promise ( ( resolve ) => setTimeout ( resolve , ms ) ) ;
236
- }
237
206
}
0 commit comments