Skip to content

Commit

Permalink
fix: ensure certificates validator is not blocked by more than 2 requ…
Browse files Browse the repository at this point in the history
…ests (#814)

refs #170
  • Loading branch information
stalniy authored Feb 7, 2025
1 parent 66cd74b commit ca0db09
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 21 deletions.
2 changes: 1 addition & 1 deletion apps/provider-proxy/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"scripts": {
"build": "rm -rf dist/* && npx tsc && esbuild server.ts --bundle --sourcemap --platform=node --target=node20.14.0 --outdir=dist",
"dev": "nodemon server.ts",
"dev:inspect": "nodemon --exec node --inspect -r ts-node/register server.ts",
"dev-nodc": "npm run dev",
"format": "prettier --write ./*.{ts,js,json} **/*.{ts,js,json}",
"lint": "eslint .",
Expand All @@ -23,7 +24,6 @@
"dependencies": {
"@akashnetwork/logging": "*",
"@akashnetwork/net": "*",
"async-sema": "^3.1.1",
"bech32": "^2.0.0",
"cors": "^2.8.5",
"express": "^4.18.2",
Expand Down
20 changes: 4 additions & 16 deletions apps/provider-proxy/src/services/CertificateValidator.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { LoggerService } from "@akashnetwork/logging";
import { SupportedChainNetworks } from "@akashnetwork/net";
import { Sema } from "async-sema";
import { bech32 } from "bech32";
import { X509Certificate } from "crypto";
import { LRUCache } from "lru-cache";
Expand All @@ -12,7 +11,7 @@ export class CertificateValidator {
max: 100_000,
ttl: 30 * 60 * 1000
});
private readonly locks: Record<string, Sema> = {};
private readonly inflightCertificates: Record<string, Promise<X509Certificate | null>> = {};

constructor(
private readonly now: () => number,
Expand Down Expand Up @@ -49,28 +48,17 @@ export class CertificateValidator {
const key = `${network}.${providerAddress}.${cert.serialNumber}`;

if (this.knownCertificatesCache.has(key)) {
// no need to create lock as we have value in cache
return this.knownCertificatesCache.get(key);
}

this.locks[key] ??= new Sema(1);

try {
await this.locks[key].acquire();
if (this.knownCertificatesCache.has(key)) {
// no need to send request, another request put the value in cache
return this.knownCertificatesCache.get(key);
}

const certificate = await this.providerService.getCertificate(network, providerAddress, cert.serialNumber);
this.inflightCertificates[key] ??= this.providerService.getCertificate(network, providerAddress, cert.serialNumber);
const certificate = await this.inflightCertificates[key];
this.knownCertificatesCache.set(key, certificate);

return certificate;
} finally {
if (this.locks[key]) {
this.locks[key].release();
delete this.locks[key];
}
delete this.inflightCertificates[key];
}
}
}
Expand Down
11 changes: 9 additions & 2 deletions apps/provider-proxy/test/services/CertificateValidator.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { X509Certificate } from "crypto";
import { setTimeout } from "timers/promises";

import { CertificateValidator, CertificateValidatorIntrumentation, CertValidationResultError } from "../../src/services/CertificateValidator";
import { ProviderService } from "../../src/services/ProviderService";
Expand Down Expand Up @@ -159,10 +160,16 @@ describe(CertificateValidator.name, () => {
commonName: "akash1rk090a6mq9gvm0h6ljf8kz8mrxglwwxsk4srxh",
serialNumber: "177831BE7F249E66"
});
const getCertificate = jest.fn(async () => cert);
const getCertificate = jest.fn(() => setTimeout(20, cert));
const validator = setup({ getCertificate });

const results = await Promise.all([validator.validate(cert, "mainnet", "provider"), validator.validate(cert, "mainnet", "provider")]);
const results = await Promise.all([
// keep-newline
validator.validate(cert, "mainnet", "provider"),
validator.validate(cert, "mainnet", "provider"),
validator.validate(cert, "mainnet", "provider"),
validator.validate(cert, "mainnet", "provider")
]);

expect(getCertificate).toHaveBeenCalledTimes(1);
expect(results[0].ok).toBe(true);
Expand Down
3 changes: 1 addition & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit ca0db09

Please sign in to comment.