From 940d09518d7c00d5381ab78c840ff772949923b4 Mon Sep 17 00:00:00 2001 From: MantisClone Date: Fri, 27 Oct 2023 16:49:43 -0400 Subject: [PATCH 1/6] Reduce getConfirmationMaxRetry to 30, getConfirmationRetryDelay to 1000 * Improve error log * Default timeout = 3000 ms defer + (30 retries * 1000 ms delay) = 33 seconds * Aligns with default timeout fetching from storage-subgraph = 30 seconds --- packages/request-client.js/src/http-config-defaults.ts | 4 ++-- packages/request-client.js/src/http-data-access.ts | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/request-client.js/src/http-config-defaults.ts b/packages/request-client.js/src/http-config-defaults.ts index d60d9e5a5a..78edc29925 100644 --- a/packages/request-client.js/src/http-config-defaults.ts +++ b/packages/request-client.js/src/http-config-defaults.ts @@ -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, diff --git a/packages/request-client.js/src/http-data-access.ts b/packages/request-client.js/src/http-data-access.ts index 1f512fb2c0..0d92672906 100644 --- a/packages/request-client.js/src/http-data-access.ts +++ b/packages/request-client.js/src/http-data-access.ts @@ -130,7 +130,12 @@ 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 after ${ + this.httpConfig.getConfirmationDeferDelay + + this.httpConfig.getConfirmationMaxRetry * this.httpConfig.getConfirmationRetryDelay + }ms. (${this.httpConfig.getConfirmationDeferDelay}ms defer delay plus ${ + this.httpConfig.getConfirmationMaxRetry + } retries with ${this.httpConfig.getConfirmationRetryDelay}ms retry delay)`, ); } result.emit('error', error); From 48dd1ad94a36b5327ec3bc4297f2d2ed61ad4e31 Mon Sep 17 00:00:00 2001 From: MantisClone Date: Fri, 27 Oct 2023 17:23:16 -0400 Subject: [PATCH 2/6] Emit error event if the transaction is not confirmed in 30 seconds --- packages/thegraph-data-access/src/data-access.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/thegraph-data-access/src/data-access.ts b/packages/thegraph-data-access/src/data-access.ts index 48ade60721..211c26f9b7 100644 --- a/packages/thegraph-data-access/src/data-access.ts +++ b/packages/thegraph-data-access/src/data-access.ts @@ -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 }); From 25b4d1ef0d1b0bcfd6b82c312764bbedeff368e5 Mon Sep 17 00:00:00 2001 From: MantisClone Date: Fri, 27 Oct 2023 17:23:51 -0400 Subject: [PATCH 3/6] Fix error message so it's not split across multiple lines in GCP logging --- .../src/request/persistTransaction.ts | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/packages/request-node/src/request/persistTransaction.ts b/packages/request-node/src/request/persistTransaction.ts index 3cb2b63d27..420a0594ee 100644 --- a/packages/request-node/src/request/persistTransaction.ts +++ b/packages/request-node/src/request/persistTransaction.ts @@ -85,18 +85,12 @@ export default class PersistTransactionHandler { // when the transaction fails, log an error dataAccessResponse.on('error', async (e) => { - const logData = [ - 'transactionHash', - 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}`); + 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 From fdd8a3219251ec93d4657c56681dd476122b1684 Mon Sep 17 00:00:00 2001 From: MantisClone Date: Fri, 27 Oct 2023 17:40:33 -0400 Subject: [PATCH 4/6] Improve client-side error message --- packages/request-client.js/src/http-data-access.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/request-client.js/src/http-data-access.ts b/packages/request-client.js/src/http-data-access.ts index 0d92672906..429c73b457 100644 --- a/packages/request-client.js/src/http-data-access.ts +++ b/packages/request-client.js/src/http-data-access.ts @@ -130,12 +130,13 @@ export default class HttpDataAccess implements DataAccessTypes.IDataAccess { let error: Error = e; if (e.response.status === 404) { error = new Error( - `Transaction confirmation not received after ${ - this.httpConfig.getConfirmationDeferDelay + - this.httpConfig.getConfirmationMaxRetry * this.httpConfig.getConfirmationRetryDelay - }ms. (${this.httpConfig.getConfirmationDeferDelay}ms defer delay plus ${ - this.httpConfig.getConfirmationMaxRetry - } retries with ${this.httpConfig.getConfirmationRetryDelay}ms retry delay)`, + `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); From 39a1fcbf534827ec890b543107175b09791709a9 Mon Sep 17 00:00:00 2001 From: MantisClone Date: Fri, 27 Oct 2023 18:00:24 -0400 Subject: [PATCH 5/6] Store error when persistTransaction fails. * This tells the user to stop polling /getConfirmedTransaction because the transaction will never be confirmed. --- .../src/request/confirmedTransactionStore.ts | 18 ++++++++++++++---- .../src/request/persistTransaction.ts | 6 +++++- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/packages/request-node/src/request/confirmedTransactionStore.ts b/packages/request-node/src/request/confirmedTransactionStore.ts index 67a4ac64f9..c7beaa196c 100644 --- a/packages/request-node/src/request/confirmedTransactionStore.ts +++ b/packages/request-node/src/request/confirmedTransactionStore.ts @@ -7,13 +7,13 @@ 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; + private store: Keyv; /** * Confirmed transactions store constructor */ - constructor(store?: Store) { - this.store = new Keyv({ + constructor(store?: Store) { + this.store = new Keyv({ namespace: 'ConfirmedTransactions', store, }); @@ -21,7 +21,7 @@ export default class ConfirmedTransactionStore { public async getConfirmedTransaction( transactionHash: string, - ): Promise { + ): Promise { return this.store.get(transactionHash); } @@ -37,4 +37,14 @@ export default class ConfirmedTransactionStore { ): Promise { 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 { + await this.store.set(transactionHash, error); + } } diff --git a/packages/request-node/src/request/persistTransaction.ts b/packages/request-node/src/request/persistTransaction.ts index 420a0594ee..c9433efbfd 100644 --- a/packages/request-node/src/request/persistTransaction.ts +++ b/packages/request-node/src/request/persistTransaction.ts @@ -84,7 +84,11 @@ export default class PersistTransactionHandler { }); // when the transaction fails, log an error - dataAccessResponse.on('error', async (e) => { + dataAccessResponse.on('error', async (e: unknown) => { + await this.confirmedTransactionStore.addFailedTransaction( + transactionHash.value, + e as Error, + ); this.logger.error(`persistTransaction error: ${e}\n transactionHash: ${transactionHash.value}, channelId: ${ clientRequest.body.channelId From a82a3e4ebf351b8c5722b1ac5bad249e61a6f77c Mon Sep 17 00:00:00 2001 From: MantisClone Date: Fri, 27 Oct 2023 18:49:58 -0400 Subject: [PATCH 6/6] Fix test --- packages/request-client.js/test/http-data-access.test.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/request-client.js/test/http-data-access.test.ts b/packages/request-client.js/test/http-data-access.test.ts index 673b0c3a11..f29929f9bd 100644 --- a/packages/request-client.js/test/http-data-access.test.ts +++ b/packages/request-client.js/test/http-data-access.test.ts @@ -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(); }); });