diff --git a/package.json b/package.json index 1708ab1..64d0c0d 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "prepare": "husky install" }, "dependencies": { - "@ardrive/ardrive-promise-cache": "^1.1.3", + "@ardrive/ardrive-promise-cache": "^1.1.4-alpha.1", "@commitlint/config-conventional": "^17.7.0", "@koa/cors": "^4.0.0", "@koa/router": "^12.0.0", diff --git a/src/api/warp.ts b/src/api/warp.ts index 346b467..16037fa 100644 --- a/src/api/warp.ts +++ b/src/api/warp.ts @@ -61,7 +61,7 @@ const contractStateCache: ReadThroughPromiseCache< cacheCapacity: 100, cacheTTL: 1000 * 30, // 30 seconds }, - readThroughFunction: (cacheKey) => readThroughToContractState(cacheKey), + readThroughFunction: readThroughToContractState, }); // Convenience class for read through caching @@ -81,13 +81,13 @@ class ContractManifestCacheKey { // Aggressively cache contract manifests since they're permanent on chain const contractManifestCache: ReadThroughPromiseCache< ContractManifestCacheKey, - any + EvaluationManifest > = new ReadThroughPromiseCache({ cacheParams: { cacheCapacity: 1000, cacheTTL: 1000 * 60 * 60 * 24 * 365, // 365 days - effectively permanent }, - readThroughFunction: (cacheKey) => readThroughToContractManifest(cacheKey), + readThroughFunction: readThroughToContractManifest, }); function createQueryParamHash(evalOptions: Partial): string { @@ -120,13 +120,13 @@ async function readThroughToContractState( ...cachedValue, evaluationOptions, }; - } else { - logger?.debug('Evaluating contract state...', { - contractTxId, - cacheKey: cacheKey.toString(), - }); } + logger?.debug('Evaluating contract state...', { + contractTxId, + cacheKey: cacheKey.toString(), + }); + // use the combined evaluation options const contract = warp .contract(contractTxId) @@ -137,14 +137,17 @@ async function readThroughToContractState( requestMap.set(cacheId, readStatePromise); readStatePromise - .catch((error) => { + .catch((error: unknown) => { logger?.debug('Failed to evaluate contract state!', { contractTxId, cacheKey: cacheKey.toString(), - error, + error: error instanceof Error ? error.message : 'Unknown error', }); }) .finally(() => { + logger?.debug('Removing request from in-flight cache.', { + cacheId, + }); // remove the cached request whether it completes or fails requestMap.delete(cacheId); }); @@ -166,36 +169,21 @@ async function readThroughToContractState( export async function getContractState({ contractTxId, warp, - evaluationOptionOverrides = DEFAULT_EVALUATION_OPTIONS, logger, }: { contractTxId: string; warp: Warp; - evaluationOptionOverrides?: Partial; logger: winston.Logger; }): Promise { try { // get the contract manifest eval options by default - const { evaluationOptions: contractDefinedEvalOptions } = - await getContractManifest({ - contractTxId, - arweave: warp.arweave, - logger, - }); - // override any contract manifest eval options with eval options provided - const combinedEvalOptions = { - ...contractDefinedEvalOptions, - ...evaluationOptionOverrides, - }; - + const { evaluationOptions = DEFAULT_EVALUATION_OPTIONS } = + await contractManifestCache.get( + new ContractManifestCacheKey(contractTxId, warp.arweave, logger), + ); // Awaiting here so that promise rejection can be caught below, wrapped, and propagated return await contractStateCache.get( - new ContractStateCacheKey( - contractTxId, - combinedEvalOptions, - warp, - logger, - ), + new ContractStateCacheKey(contractTxId, evaluationOptions, warp, logger), ); } catch (error) { // throw an eval here so we can properly return correct status code @@ -215,11 +203,7 @@ async function readThroughToContractManifest({ contractTxId, arweave, logger, -}: { - contractTxId: string; - arweave: Arweave; - logger?: winston.Logger; -}): Promise { +}: ContractManifestCacheKey): Promise { logger?.debug('Reading through to contract manifest...', { contractTxId, }); @@ -231,20 +215,6 @@ async function readThroughToContractManifest({ return contractManifest; } -export async function getContractManifest({ - contractTxId, - arweave, - logger, -}: { - contractTxId: string; - arweave: Arweave; - logger?: winston.Logger; -}): Promise { - return contractManifestCache.get( - new ContractManifestCacheKey(contractTxId, arweave, logger), - ); -} - export function tagsToObject(tags: Tag[]): { [x: string]: string; } { diff --git a/src/app.ts b/src/app.ts index f05d2aa..2613694 100644 --- a/src/app.ts +++ b/src/app.ts @@ -30,7 +30,7 @@ const errorCounter = new promClient.Counter({ // catch any floating errors, swallow them and increment prometheus counter process.on('uncaughtException', (err) => { - logger.error(err); + logger.error('Uncaught exception!', err); errorCounter.inc(); }); diff --git a/yarn.lock b/yarn.lock index c1ff476..fbb2c60 100644 --- a/yarn.lock +++ b/yarn.lock @@ -117,10 +117,10 @@ dependencies: xss "^1.0.8" -"@ardrive/ardrive-promise-cache@^1.1.3": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@ardrive/ardrive-promise-cache/-/ardrive-promise-cache-1.1.3.tgz#93dc04f54bcccfc90b97d9aeb1095bb6374eacc8" - integrity sha512-jPFlnVUlHcW+LEptyUyXl2oZ6JZeuWTycZ/tfOWxXL9go+0icUHUWibIvJAuqeR4EjBFsT953BOibplPsZ/b1w== +"@ardrive/ardrive-promise-cache@^1.1.4-alpha.1": + version "1.1.4-alpha.1" + resolved "https://registry.yarnpkg.com/@ardrive/ardrive-promise-cache/-/ardrive-promise-cache-1.1.4-alpha.1.tgz#a35507eff7f4ecd13c0a692f2e6d8f7450fd344f" + integrity sha512-XiX230ReWAsVc9Nr9e65qdRgip4TmlOQhKFozrX3FUmh+Ee5ry0Q4B5XMmn/jgGOuAIrGeI8tO+vCW/y90uS6A== dependencies: "@alexsasharegan/simple-cache" "^3.3.3"