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

Commit

Permalink
fix(graphql): add abort controller support on interactions endpoint
Browse files Browse the repository at this point in the history
We use a synchrnoized abort signal for both interaction and state evaluation to ensure we do not continue doing work when we have thrown a timeout error.
  • Loading branch information
dtfiedler committed Dec 16, 2023
1 parent 0e4b28f commit 5c676ed
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 2 deletions.
29 changes: 29 additions & 0 deletions src/api/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ import {
} from 'warp-contracts';
import { ReadThroughPromiseCache } from '@ardrive/ardrive-promise-cache';
import winston from 'winston';
import { EvaluationTimeoutError } from '../errors';

export const MAX_REQUEST_SIZE = 100;

export async function getDeployedContractsByWallet(
arweave: Arweave,
params: { address: string },
signal?: AbortSignal,
): Promise<{ ids: string[] }> {
const { address } = params;
let hasNextPage = false;
Expand Down Expand Up @@ -71,9 +73,16 @@ export async function getDeployedContractsByWallet(
}`,
};

if (signal?.aborted) {
throw new EvaluationTimeoutError();
}

const { status, ...response } = await arweave.api.post(
'/graphql',
queryObject,
{
signal,
},
);
if (status !== 200) {
throw Error(
Expand Down Expand Up @@ -115,6 +124,7 @@ class ContractInteractionsCacheKey {
public readonly blockHeight: number | undefined,
public readonly address?: string | undefined,
public readonly logger?: winston.Logger | undefined,
public readonly signal?: AbortSignal | undefined,
) {}

toString(): string {
Expand Down Expand Up @@ -147,11 +157,13 @@ export async function getWalletInteractionsForContract({
address,
blockHeight,
logger,
signal,
}: {
arweave: Arweave;
contractTxId: string;
address?: string | undefined;
blockHeight?: number | undefined;
signal?: AbortSignal;
logger?: winston.Logger | undefined;
}) {
return contractInteractionsCache.get(
Expand All @@ -161,6 +173,7 @@ export async function getWalletInteractionsForContract({
blockHeight,
address,
logger,
signal,
),
);
}
Expand All @@ -176,6 +189,7 @@ export async function readThroughToWalletInteractionsForContract(
address,
blockHeight: blockHeightFilter,
logger,
signal,
} = cacheKey;
logger?.debug('Reading through to wallet interactions for contract...', {
contractTxId,
Expand Down Expand Up @@ -242,9 +256,16 @@ export async function readThroughToWalletInteractionsForContract(
}`,
};

if (signal?.aborted) {
throw new EvaluationTimeoutError();
}

const { status, data } = await arweave.api.post<GQLResultInterface>(
'/graphql',
queryObject,
{
signal,
},
);

if (status !== 200) {
Expand Down Expand Up @@ -309,6 +330,7 @@ export async function readThroughToWalletInteractionsForContract(
export async function getContractsTransferredToOrControlledByWallet(
arweave: Arweave,
params: { address: string },
signal?: AbortSignal,
): Promise<{ ids: string[] }> {
const { address } = params;
let hasNextPage = false;
Expand Down Expand Up @@ -406,9 +428,16 @@ export async function getContractsTransferredToOrControlledByWallet(
}`,
};

if (signal?.aborted) {
throw new EvaluationTimeoutError();
}

const { status, ...response } = await arweave.api.post(
'/graphql',
queryObject,
{
signal,
},
);
if (status !== 200) {
throw Error(
Expand Down
1 change: 1 addition & 0 deletions src/api/warp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ export async function readThroughToContractReadInteraction(
.setEvaluationOptions(evaluationOptions);

// set cached value for multiple requests during initial promise
// TODO: add abort signal when view state supports it
const readInteractionPromise = contract.viewState({
function: functionName,
...input,
Expand Down
4 changes: 2 additions & 2 deletions src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

// TODO: we could put a prometheus metric here to help fine tune what our evaluation limit should be
export class BaseError extends Error {
super(message: string) {
this.message = message;
Expand All @@ -24,7 +23,8 @@ export class BaseError extends Error {
}
export class EvaluationTimeoutError extends BaseError {
constructor() {
super(`Evaluation timed out for contract.`);
super(`Evaluation timed out.`);
// TODO: we could put a prometheus metric here to help fine tune what our evaluation limit should be
}
}
export class EvaluationError extends BaseError {}
Expand Down
5 changes: 5 additions & 0 deletions src/routes/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { getContractReadInteraction, getContractState } from '../api/warp';
import { getWalletInteractionsForContract } from '../api/graphql';
import { NotFoundError } from '../errors';
import { mismatchedInteractionCount } from '../metrics';
import { DEFAULT_STATE_EVALUATION_TIMEOUT_MS } from '../constants';

export async function contractHandler(ctx: KoaContext) {
const {
Expand Down Expand Up @@ -81,6 +82,8 @@ export async function contractInteractionsHandler(ctx: KoaContext) {
* TODO: add a read through promise cache here that uses the following logic as the resulting promise. The cache key should contain the contractTxId, sortKey, blockHeight, address, page, and pageSize.
*/

// use a synchronized abort signal to stop execution of both when either times out
const abortSignal = AbortSignal.timeout(DEFAULT_STATE_EVALUATION_TIMEOUT_MS);
const [
{ validity, errorMessages, evaluationOptions, sortKey: evaluatedSortKey },
{ interactions },
Expand All @@ -91,13 +94,15 @@ export async function contractInteractionsHandler(ctx: KoaContext) {
logger,
sortKey: requestedSortKey,
blockHeight: requestedBlockHeight,
signal: abortSignal,
}),
getWalletInteractionsForContract({
arweave,
address,
contractTxId,
blockHeight: requestedBlockHeight,
logger,
signal: abortSignal,
}),
]);

Expand Down

0 comments on commit 5c676ed

Please sign in to comment.