@@ -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,15 @@ 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 . link ( resultFilePath , latestResultFilePath ) ;
87
+ } ) ;
98
88
}
99
89
}
100
90
@@ -134,50 +124,36 @@ export class DiskBasedResultStorage implements AccuracyResultStorage {
134
124
return ;
135
125
}
136
126
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 ) ;
141
129
if ( ! accuracyResult ) {
142
130
throw new Error ( "Expected at-least initial accuracy result to be present" ) ;
143
131
}
144
132
145
133
const existingPromptIdx = accuracyResult . promptResults . findIndex ( ( result ) => result . prompt === prompt ) ;
146
134
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 ,
151
146
{
152
- ...accuracyResult ,
153
- promptResults : [
154
- ...accuracyResult . promptResults ,
155
- {
156
- prompt,
157
- expectedToolCalls,
158
- modelResponses : [ modelResponse ] ,
159
- } ,
160
- ] ,
147
+ prompt,
148
+ expectedToolCalls,
149
+ modelResponses : [ modelResponse ] ,
161
150
} ,
162
- null ,
163
- 2
164
- )
165
- ) ;
151
+ ] ,
152
+ } ;
166
153
}
167
154
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
+ } ) ;
181
157
}
182
158
183
159
close ( ) : Promise < void > {
@@ -206,20 +182,16 @@ export class DiskBasedResultStorage implements AccuracyResultStorage {
206
182
}
207
183
}
208
184
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 ?.( ) ;
223
195
}
224
196
}
225
197
@@ -230,8 +202,4 @@ export class DiskBasedResultStorage implements AccuracyResultStorage {
230
202
private getLatestResultFilePath ( commitSHA : string ) : string {
231
203
return path . join ( ACCURACY_RESULTS_DIR , commitSHA , `${ LATEST_ACCURACY_RUN_NAME } .json` ) ;
232
204
}
233
-
234
- private waitFor ( ms : number ) {
235
- return new Promise ( ( resolve ) => setTimeout ( resolve , ms ) ) ;
236
- }
237
205
}
0 commit comments