@dev-blinq/cucumber_client 1.0.1186-dev → 1.0.1188-dev
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -383,7 +383,7 @@ class LocalAgent {
|
|
|
383
383
|
error: command.data.errorMessage,
|
|
384
384
|
});
|
|
385
385
|
agent.stepFailResolve(command.data.errorMessage);
|
|
386
|
-
logger.
|
|
386
|
+
logger.error("Step fail, " + command.data.errorMessage);
|
|
387
387
|
} else {
|
|
388
388
|
agent.stepEndResolve();
|
|
389
389
|
logger.info("Step end");
|
|
@@ -193,7 +193,8 @@ class ScenarioReport {
|
|
|
193
193
|
fs.writeFileSync(path, zipBlob);
|
|
194
194
|
return path;
|
|
195
195
|
}
|
|
196
|
-
|
|
196
|
+
// Note to future self:
|
|
197
|
+
// Increased the max retries to 3 and added exponential backoff to increase consistency but traded off availability :)
|
|
197
198
|
async _uploadScenario() {
|
|
198
199
|
try {
|
|
199
200
|
const scenarioDoc = await this.scenarioUploadService.createScenarioDocument(this.name);
|
|
@@ -201,62 +202,91 @@ class ScenarioReport {
|
|
|
201
202
|
const projectId = scenarioDoc.project_id;
|
|
202
203
|
this.scenario_id = scenarioDocId;
|
|
203
204
|
this._saveToFile();
|
|
204
|
-
|
|
205
|
-
// console.log("scenarioDocId", scenarioDocId);
|
|
206
205
|
await this.sendRetrainStats(scenarioDocId);
|
|
207
|
-
// create zip file
|
|
208
206
|
if (process.env.NODE_ENV_BLINQ === "local") {
|
|
209
|
-
|
|
210
|
-
// upload to server
|
|
211
|
-
const formData = new FormData();
|
|
212
|
-
// const file = File(zipFileBlob, "report.zip");
|
|
213
|
-
formData.append(scenarioDocId, fs.readFileSync(zipFilePath), "report.zip");
|
|
214
|
-
await this.scenarioUploadService.upload(formData);
|
|
207
|
+
await this._uploadLocalBundle(scenarioDocId);
|
|
215
208
|
} else {
|
|
216
|
-
|
|
217
|
-
fs.writeFileSync(path.join(this.scenarioPath, "scenario.json"), JSON.stringify(report, null, 2));
|
|
218
|
-
const fileUris = [
|
|
219
|
-
...this.getFileUrisScreenShotDir(this.scenarioPath),
|
|
220
|
-
"scenario.json",
|
|
221
|
-
"network.json",
|
|
222
|
-
"editorLogs.log",
|
|
223
|
-
];
|
|
224
|
-
const networkJsonPath = path.join(this.scenarioPath, "network.json");
|
|
225
|
-
if (!fs.existsSync(networkJsonPath)) {
|
|
226
|
-
fs.writeFileSync(networkJsonPath, JSON.stringify({}), "utf-8");
|
|
227
|
-
}
|
|
228
|
-
const presignedUrls = await this.scenarioUploadService.getPresignedUrls(fileUris, scenarioDocId);
|
|
229
|
-
for (let i = 0; i < fileUris.length; i += BATCH_SIZE) {
|
|
230
|
-
const batch = fileUris.slice(i, Math.min(i + BATCH_SIZE, fileUris.length));
|
|
231
|
-
await Promise.all(
|
|
232
|
-
batch
|
|
233
|
-
.filter((fileUrl) => presignedUrls[fileUrl] !== undefined)
|
|
234
|
-
.map(async (fileUrl) => {
|
|
235
|
-
const filePath = path.join(this.scenarioPath, fileUrl);
|
|
236
|
-
for (let j = 0; j < MAX_RETRIES; j++) {
|
|
237
|
-
const success = await this.scenarioUploadService.uploadFile(filePath, presignedUrls[fileUrl]);
|
|
238
|
-
if (success) {
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
console.error("Failed to upload file", fileUrl);
|
|
243
|
-
})
|
|
244
|
-
);
|
|
245
|
-
}
|
|
246
|
-
await this.scenarioUploadService.uploadComplete(scenarioDocId, projectId);
|
|
209
|
+
await this._uploadRemoteBundle(scenarioDocId, projectId);
|
|
247
210
|
}
|
|
248
211
|
logger.info("Scenario uploaded successfully");
|
|
249
|
-
|
|
250
212
|
this.logReportLink(projectId, scenarioDocId);
|
|
251
|
-
|
|
252
|
-
// delete zip file
|
|
253
|
-
// fs.unlinkSync(this.scenarioPath + '/example.zip');
|
|
254
213
|
} catch (err) {
|
|
255
|
-
logger.
|
|
256
|
-
logger.debug(err);
|
|
257
|
-
//console.error(err);
|
|
214
|
+
logger.error("Scenario uploaded failed");
|
|
215
|
+
logger.debug("Error while uploading : ", err);
|
|
258
216
|
}
|
|
259
217
|
}
|
|
218
|
+
// Local environment uploader decomposed the function for better readability
|
|
219
|
+
async _uploadLocalBundle(scenarioDocId) {
|
|
220
|
+
const zipFilePath = await this.createScenarioZip();
|
|
221
|
+
const formData = new FormData();
|
|
222
|
+
formData.append("scenarioId", scenarioDocId);
|
|
223
|
+
formData.append("file", fs.createReadStream(zipFilePath));
|
|
224
|
+
|
|
225
|
+
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
|
226
|
+
try {
|
|
227
|
+
await this.scenarioUploadService.upload(formData);
|
|
228
|
+
fs.unlinkSync(zipFilePath);
|
|
229
|
+
return;
|
|
230
|
+
} catch (err) {
|
|
231
|
+
logger.debug("Local upload attempt failed", { attempt, error: err });
|
|
232
|
+
// added delays between retries for better consistency over availability
|
|
233
|
+
await this._delay(2 ** attempt * 1000);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
throw new Error(`Local upload failed after ${MAX_RETRIES} attempts`);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// decomposed the function for better readability this function is used to upload
|
|
240
|
+
async _uploadRemoteBundle(scenarioDocId, projectId) {
|
|
241
|
+
const report = getJsonReport(this);
|
|
242
|
+
fs.writeFileSync(path.join(this.scenarioPath, "scenario.json"), JSON.stringify(report, null, 2));
|
|
243
|
+
|
|
244
|
+
const fileUris = [
|
|
245
|
+
...this.getFileUrisScreenShotDir(this.scenarioPath),
|
|
246
|
+
"scenario.json",
|
|
247
|
+
"network.json",
|
|
248
|
+
"editorLogs.log",
|
|
249
|
+
];
|
|
250
|
+
const networkJsonPath = path.join(this.scenarioPath, "network.json");
|
|
251
|
+
if (!fs.existsSync(networkJsonPath)) {
|
|
252
|
+
fs.writeFileSync(networkJsonPath, JSON.stringify({}), "utf-8");
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const presignedUrls = await this.scenarioUploadService.getPresignedUrls(fileUris, scenarioDocId);
|
|
256
|
+
const missing = fileUris.filter((uri) => !presignedUrls[uri]);
|
|
257
|
+
if (missing.length) {
|
|
258
|
+
throw new Error(`Missing presigned URLs for: ${missing.join(", ")}`);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Upload files in batches with retries
|
|
262
|
+
for (let i = 0; i < fileUris.length; i += BATCH_SIZE) {
|
|
263
|
+
const batch = fileUris.slice(i, i + BATCH_SIZE);
|
|
264
|
+
await Promise.all(batch.map((uri) => this._retryUploadFile(uri, presignedUrls[uri])));
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
await this.scenarioUploadService.uploadComplete(scenarioDocId, projectId);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Retry helper it will retry the upload of a file if it fails given file uri and url here Max_retires is and each retiry wait time : 2secs ,4secs, 8 secs
|
|
271
|
+
// Note to self : if the still upload fails a lot we have to investigate the file formats too
|
|
272
|
+
async _retryUploadFile(fileUri, url) {
|
|
273
|
+
const filePath = path.join(this.scenarioPath, fileUri);
|
|
274
|
+
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
|
275
|
+
try {
|
|
276
|
+
await this.scenarioUploadService.uploadFile(filePath, url);
|
|
277
|
+
return;
|
|
278
|
+
} catch (err) {
|
|
279
|
+
logger.debug("Upload file attempt failed ", { fileUri, attempt, error: err });
|
|
280
|
+
await this._delay(2 ** attempt * 1000);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
throw new Error(`Failed to upload file ${fileUri} after ${MAX_RETRIES} attempts`);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Utility delay can be used to delay anything (Note to self : Replace it with the built in delay function later)
|
|
287
|
+
_delay(ms) {
|
|
288
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
289
|
+
}
|
|
260
290
|
|
|
261
291
|
logReportLink(projectId, scenarioId) {
|
|
262
292
|
let baseUrl = "https://www.app.blinq.io";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dev-blinq/cucumber_client",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1188-dev",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "bin/index.js",
|
|
6
6
|
"types": "bin/index.d.ts",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"@cucumber/tag-expressions": "^6.1.1",
|
|
29
29
|
"@dev-blinq/cucumber-js": "1.0.172-dev",
|
|
30
30
|
"@faker-js/faker": "^8.1.0",
|
|
31
|
-
"automation_model": "1.0.
|
|
31
|
+
"automation_model": "1.0.719-dev",
|
|
32
32
|
"axios": "^1.7.4",
|
|
33
33
|
"chokidar": "^3.6.0",
|
|
34
34
|
"create-require": "^1.1.1",
|