Skip to content
This repository has been archived by the owner on Sep 16, 2024. It is now read-only.

fix(PE-4612): testing an updating promise cache that does not await on puts #43

Merged
merged 3 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
71 changes: 18 additions & 53 deletions src/api/warp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@
EvaluationOptions,
Warp,
} from 'warp-contracts';
import {
DEFAULT_EVALUATION_OPTIONS,
EVALUATION_TIMEOUT_MS,
allowedContractTypes,
} from '../constants';
import { EVALUATION_TIMEOUT_MS, allowedContractTypes } from '../constants';
import { ContractType } from '../types';
import * as _ from 'lodash';
import { EvaluationTimeoutError } from '../errors';
Expand All @@ -18,7 +14,7 @@
import { ReadThroughPromiseCache } from '@ardrive/ardrive-promise-cache';
import winston from 'winston';

export type EvaluatedContractState = EvalStateResult<any> & {

Check warning on line 17 in src/api/warp.ts

View workflow job for this annotation

GitHub Actions / build (lint:check)

Unexpected any. Specify a different type
evaluationOptions?: Partial<EvaluationOptions>;
};

Expand All @@ -29,7 +25,7 @@
}

// cache duplicate requests on the same instance within a short period of time
const requestMap: Map<string, Promise<any> | undefined> = new Map();

Check warning on line 28 in src/api/warp.ts

View workflow job for this annotation

GitHub Actions / build (lint:check)

Unexpected any. Specify a different type

// Convenience class for read through caching
class ContractStateCacheKey {
Expand Down Expand Up @@ -61,7 +57,7 @@
cacheCapacity: 100,
cacheTTL: 1000 * 30, // 30 seconds
},
readThroughFunction: (cacheKey) => readThroughToContractState(cacheKey),
readThroughFunction: readThroughToContractState,
});

// Convenience class for read through caching
Expand All @@ -81,13 +77,13 @@
// Aggressively cache contract manifests since they're permanent on chain
const contractManifestCache: ReadThroughPromiseCache<
ContractManifestCacheKey,
any

Check warning on line 80 in src/api/warp.ts

View workflow job for this annotation

GitHub Actions / build (lint:check)

Unexpected any. Specify a different type
> = 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<EvaluationOptions>): string {
Expand Down Expand Up @@ -120,13 +116,13 @@
...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)
Expand All @@ -137,14 +133,17 @@
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 cached rqeuest from barrier map.', {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
logger?.debug('Removing cached rqeuest from barrier map.', {
logger?.debug('Removing request from in-flight cache.', {

Copy link
Collaborator Author

@dtfiedler dtfiedler Sep 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cacheId,
});
// remove the cached request whether it completes or fails
requestMap.delete(cacheId);
});
Expand All @@ -166,36 +165,20 @@
export async function getContractState({
contractTxId,
warp,
evaluationOptionOverrides = DEFAULT_EVALUATION_OPTIONS,
logger,
}: {
contractTxId: string;
warp: Warp;
evaluationOptionOverrides?: Partial<EvaluationOptions>;
logger: winston.Logger;
}): Promise<EvaluatedContractState> {
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 } = 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
Expand All @@ -215,11 +198,7 @@
contractTxId,
arweave,
logger,
}: {
contractTxId: string;
arweave: Arweave;
logger?: winston.Logger;
}): Promise<EvaluationManifest> {
}: ContractManifestCacheKey): Promise<EvaluationManifest> {
logger?.debug('Reading through to contract manifest...', {
contractTxId,
});
Expand All @@ -231,20 +210,6 @@
return contractManifest;
}

export async function getContractManifest({
contractTxId,
arweave,
logger,
}: {
contractTxId: string;
arweave: Arweave;
logger?: winston.Logger;
}): Promise<EvaluationManifest> {
return contractManifestCache.get(
new ContractManifestCacheKey(contractTxId, arweave, logger),
);
}

export function tagsToObject(tags: Tag[]): {
[x: string]: string;
} {
Expand Down
2 changes: 1 addition & 1 deletion src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});

Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down
Loading