Skip to content

Commit 04838e2

Browse files
authored
Fix VerificationService to handle errors thrown by workerPool.run (#2279)
1 parent fb5ae20 commit 04838e2

File tree

2 files changed

+96
-30
lines changed

2 files changed

+96
-30
lines changed

services/server/src/server/services/VerificationService.ts

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -290,15 +290,7 @@ export class VerificationService {
290290
traceId: asyncLocalStorage.getStore()?.traceId,
291291
};
292292

293-
const task = this.workerPool
294-
.run(input, { name: "verifyFromJsonInput" })
295-
.then((output: VerifyOutput) => {
296-
return this.handleWorkerResponse(verificationId, output);
297-
})
298-
.finally(() => {
299-
this.runningTasks.delete(task);
300-
});
301-
this.runningTasks.add(task);
293+
this.verifyViaWorker(verificationId, "verifyFromJsonInput", input);
302294

303295
return verificationId;
304296
}
@@ -325,15 +317,7 @@ export class VerificationService {
325317
traceId: asyncLocalStorage.getStore()?.traceId,
326318
};
327319

328-
const task = this.workerPool
329-
.run(input, { name: "verifyFromMetadata" })
330-
.then((output: VerifyOutput) => {
331-
return this.handleWorkerResponse(verificationId, output);
332-
})
333-
.finally(() => {
334-
this.runningTasks.delete(task);
335-
});
336-
this.runningTasks.add(task);
320+
this.verifyViaWorker(verificationId, "verifyFromMetadata", input);
337321

338322
return verificationId;
339323
}
@@ -356,24 +340,21 @@ export class VerificationService {
356340
traceId: asyncLocalStorage.getStore()?.traceId,
357341
};
358342

359-
const task = this.workerPool
360-
.run(input, { name: "verifyFromEtherscan" })
361-
.then((output: VerifyOutput) => {
362-
return this.handleWorkerResponse(verificationId, output);
363-
})
364-
.finally(() => {
365-
this.runningTasks.delete(task);
366-
});
367-
this.runningTasks.add(task);
343+
this.verifyViaWorker(verificationId, "verifyFromEtherscan", input);
368344

369345
return verificationId;
370346
}
371347

372-
private async handleWorkerResponse(
348+
private async verifyViaWorker(
373349
verificationId: VerificationJobId,
374-
output: VerifyOutput,
350+
functionName: string,
351+
input:
352+
| VerifyFromJsonInput
353+
| VerifyFromMetadataInput
354+
| VerifyFromEtherscanInput,
375355
): Promise<void> {
376-
return Promise.resolve(output)
356+
const task = this.workerPool
357+
.run(input, { name: functionName })
377358
.then((output: VerifyOutput) => {
378359
if (output.verificationExport) {
379360
return output.verificationExport;
@@ -437,6 +418,10 @@ export class VerificationService {
437418
new Date(),
438419
errorExport,
439420
]);
421+
})
422+
.finally(() => {
423+
this.runningTasks.delete(task);
440424
});
425+
this.runningTasks.add(task);
441426
}
442427
}

services/server/test/unit/VerificationService.spec.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,12 @@ import config from "config";
88
import rimraf from "rimraf";
99
import { StorageService } from "../../src/server/services/StorageService";
1010
import { RWStorageIdentifiers } from "../../src/server/services/storageServices/identifiers";
11+
import sinon from "sinon";
12+
import { EtherscanResult } from "../../src/server/services/utils/etherscan-util";
1113

1214
describe("VerificationService", function () {
15+
const sandbox = sinon.createSandbox();
16+
1317
beforeEach(function () {
1418
// Clear any previously nocked interceptors
1519
nock.cleanAll();
@@ -18,6 +22,7 @@ describe("VerificationService", function () {
1822
afterEach(function () {
1923
// Ensure that all nock interceptors have been used
2024
nock.isDone();
25+
sandbox.restore();
2126
});
2227

2328
it("should initialize compilers", async function () {
@@ -97,4 +102,80 @@ describe("VerificationService", function () {
97102
expect(fs.existsSync(path.join(downloadDir, release))).to.be.true;
98103
});
99104
});
105+
106+
it("should handle workerPool.run errors and set job error as internal_error", async function () {
107+
const mockStorageService = {
108+
performServiceOperation: sandbox.stub(),
109+
} as any;
110+
111+
// Mock the storage service calls
112+
const verificationId = "test-verification-id";
113+
mockStorageService.performServiceOperation
114+
.withArgs("storeVerificationJob")
115+
.resolves(verificationId);
116+
117+
mockStorageService.performServiceOperation
118+
.withArgs("setJobError")
119+
.resolves();
120+
121+
const verificationService = new VerificationService(
122+
{
123+
initCompilers: false,
124+
sourcifyChainMap: {},
125+
solcRepoPath: config.get("solcRepo"),
126+
solJsonRepoPath: config.get("solJsonRepo"),
127+
vyperRepoPath: config.get("vyperRepo"),
128+
},
129+
mockStorageService,
130+
);
131+
132+
// Mock the workerPool.run to throw an error
133+
const workerPoolStub = sandbox.stub(
134+
verificationService["workerPool"],
135+
"run",
136+
);
137+
workerPoolStub.rejects(new Error("Worker pool error"));
138+
139+
const mockEtherscanResult: EtherscanResult = {
140+
ContractName: "TestContract",
141+
SourceCode: "contract TestContract {}",
142+
ABI: "[]",
143+
CompilerVersion: "v0.8.26+commit.8a97fa7a",
144+
OptimizationUsed: "0",
145+
Runs: "200",
146+
ConstructorArguments: "",
147+
EVMVersion: "default",
148+
Library: "",
149+
LicenseType: "",
150+
Proxy: "0",
151+
Implementation: "",
152+
SwarmSource: "",
153+
};
154+
155+
// Call the method that should handle worker errors
156+
verificationService.verifyFromEtherscanViaWorker(
157+
"test-endpoint",
158+
"1",
159+
"0x1234567890123456789012345678901234567890",
160+
mockEtherscanResult,
161+
);
162+
163+
// Wait for the async task to complete
164+
await new Promise((resolve) => setTimeout(resolve, 1));
165+
166+
// Verify the job error was set with internal_error
167+
const setJobErrorCall = mockStorageService.performServiceOperation
168+
.getCalls()
169+
.find((call: any) => call.args[0] === "setJobError");
170+
expect(setJobErrorCall).to.not.be.undefined;
171+
172+
// The setJobError call has args: ["setJobError", [verificationId, Date, errorExport]]
173+
const setJobErrorArgs = setJobErrorCall.args[1];
174+
expect(setJobErrorArgs[0]).to.equal(verificationId);
175+
expect(setJobErrorArgs[1]).to.be.instanceOf(Date);
176+
expect(setJobErrorArgs[2]).to.deep.include({
177+
customCode: "internal_error",
178+
});
179+
expect(setJobErrorArgs[2].errorId).to.be.a("string");
180+
});
100181
});

0 commit comments

Comments
 (0)