Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: persistTransaction timeout #1224

Merged
merged 10 commits into from
Nov 10, 2023
4 changes: 2 additions & 2 deletions packages/request-client.js/src/http-config-defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ const config: ClientTypes.IHttpDataAccessConfig = {
httpRequestRetryDelay: 100,
httpRequestExponentialBackoffDelay: 0,
httpRequestMaxExponentialBackoffDelay: 30000,
getConfirmationMaxRetry: 500,
getConfirmationRetryDelay: 3000,
getConfirmationMaxRetry: 30,
getConfirmationRetryDelay: 1000,
getConfirmationExponentialBackoffDelay: 0,
getConfirmationMaxExponentialBackoffDelay: 30000,
getConfirmationDeferDelay: 3000,
Expand Down
8 changes: 7 additions & 1 deletion packages/request-client.js/src/http-data-access.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,13 @@ export default class HttpDataAccess implements DataAccessTypes.IDataAccess {
let error: Error = e;
if (e.response.status === 404) {
error = new Error(
`Transaction confirmation not receive after ${this.httpConfig.getConfirmationMaxRetry} retries`,
`Transaction confirmation not received. Try polling
getTransactionsByChannelId() until the transaction is confirmed.
deferDelay: ${this.httpConfig.getConfirmationDeferDelay}ms,
maxRetries: ${this.httpConfig.getConfirmationMaxRetry},
retryDelay: ${this.httpConfig.getConfirmationRetryDelay}ms,
exponentialBackoffDelay: ${this.httpConfig.getConfirmationExponentialBackoffDelay}ms,
maxExponentialBackoffDelay: ${this.httpConfig.getConfirmationMaxExponentialBackoffDelay}ms`,
);
}
result.emit('error', error);
Expand Down
8 changes: 7 additions & 1 deletion packages/request-client.js/test/http-data-access.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,13 @@ describe('HttpDataAccess', () => {
});
void httpDataAccess.persistTransaction({}, '', []).then((returnPersistTransaction) => {
returnPersistTransaction.on('error', (e: any) => {
expect(e.message).toBe('Transaction confirmation not receive after 0 retries');
expect(e.message).toBe(`Transaction confirmation not received. Try polling
getTransactionsByChannelId() until the transaction is confirmed.
deferDelay: 0ms,
maxRetries: 0,
retryDelay: 1000ms,
exponentialBackoffDelay: 0ms,
maxExponentialBackoffDelay: 30000ms`);
done();
});
});
Expand Down
18 changes: 14 additions & 4 deletions packages/request-node/src/request/confirmedTransactionStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,21 @@ import Keyv, { Store } from 'keyv';
* The client can call the getConfirmed entry point, to get the confirmed event.
*/
export default class ConfirmedTransactionStore {
private store: Keyv<DataAccessTypes.IReturnPersistTransactionRaw>;
private store: Keyv<DataAccessTypes.IReturnPersistTransactionRaw | Error>;

/**
* Confirmed transactions store constructor
*/
constructor(store?: Store<DataAccessTypes.IReturnPersistTransaction>) {
this.store = new Keyv<DataAccessTypes.IReturnPersistTransaction>({
constructor(store?: Store<DataAccessTypes.IReturnPersistTransaction | Error>) {
this.store = new Keyv<DataAccessTypes.IReturnPersistTransaction | Error>({
namespace: 'ConfirmedTransactions',
store,
});
}

public async getConfirmedTransaction(
transactionHash: string,
): Promise<DataAccessTypes.IReturnPersistTransactionRaw | undefined> {
): Promise<DataAccessTypes.IReturnPersistTransactionRaw | Error | undefined> {
return this.store.get(transactionHash);
}

Expand All @@ -37,4 +37,14 @@ export default class ConfirmedTransactionStore {
): Promise<void> {
await this.store.set(transactionHash, result);
}

/**
* Stores the error
*
* @param transactionHash hash of the transaction
* @param error error of the event "error"
*/
public async addFailedTransaction(transactionHash: string, error: Error): Promise<void> {
await this.store.set(transactionHash, error);
}
}
22 changes: 10 additions & 12 deletions packages/request-node/src/request/persistTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,19 +84,17 @@ export default class PersistTransactionHandler {
});

// when the transaction fails, log an error
dataAccessResponse.on('error', async (e) => {
const logData = [
'transactionHash',
dataAccessResponse.on('error', async (e: unknown) => {
await this.confirmedTransactionStore.addFailedTransaction(
transactionHash.value,
'channelId',
clientRequest.body.channelId,
'topics',
clientRequest.body.topics,
'transactionData',
JSON.stringify(clientRequest.body.transactionData),
].join('\n');

this.logger.error(`persistTransaction error: ${e}. \n${logData}`);
e as Error,
);
this.logger.error(`persistTransaction error: ${e}\n
transactionHash: ${transactionHash.value}, channelId: ${
clientRequest.body.channelId
}, topics: ${clientRequest.body.topics}, transactionData: ${JSON.stringify(
clientRequest.body.transactionData,
)}`);
});

// Log the request time
Expand Down
5 changes: 4 additions & 1 deletion packages/thegraph-data-access/src/data-access.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ export class TheGraphDataAccess extends CombinedDataAccess {
result.on('confirmed', (receipt) => {
this.fetchConfirmedTransaction(channelId, receipt)
.then((confirmedReceipt) => eventEmitter.emit('confirmed', confirmedReceipt))
.catch(() => this.logger.warn(`Could not confirm channel ${channelId}`));
.catch(() => {
this.logger.error(`Could not confirm channel ${channelId} after 30s`);
eventEmitter.emit('error', new Error(`Could not confirm channel ${channelId} after 30s`));
});
});
result.on('error', (e) => eventEmitter.emit('error', e));
return Object.assign(eventEmitter, { meta: result.meta, result: result.result });
Expand Down