Skip to content
This repository was archived by the owner on Apr 22, 2025. It is now read-only.

Commit a5da38f

Browse files
Added eventListener to fix unhandledRejection (#606)
Instead of rejecting the notification promise on failure, resolve with an error argument. This avoids the possibility of the promise being rejected before it is awaited. Signed-off-by: sapthasurendran <[email protected]>
1 parent 4e37f24 commit a5da38f

File tree

3 files changed

+35
-15
lines changed

3 files changed

+35
-15
lines changed

fabric-network/src/impl/event/transactioneventhandler.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {TransactionError} from '../../errors/transactionerror';
1313

1414
import * as Logger from '../../logger';
1515
import {DefaultEventHandlerOptions} from '../../gateway';
16+
1617
const logger = Logger.getLogger('TransactionEventHandler');
1718

1819
export interface TxEventHandler {
@@ -43,13 +44,12 @@ export class TransactionEventHandler implements TxEventHandler {
4344

4445
private readonly options: DefaultEventHandlerOptions;
4546
private readonly peers: Endorser[];
46-
private readonly notificationPromise: Promise<void>;
47+
private readonly notificationPromise: Promise<Error|undefined>;
4748
private readonly unrespondedPeers: Set<Endorser>;
4849
private readonly listener: CommitListener = this.eventCallback.bind(this);
4950
private readonly strategySuccessCallback = this.strategySuccess.bind(this);
5051
private readonly strategyFailCallback = this.strategyFail.bind(this);
51-
private resolveNotificationPromise!: () => void;
52-
private rejectNotificationPromise!: (reason: Error) => void;
52+
private resolveNotificationPromise!: (err?: Error) => void;
5353
private timeoutHandler?: NodeJS.Timeout;
5454

5555
/**
@@ -76,9 +76,8 @@ export class TransactionEventHandler implements TxEventHandler {
7676
this.peers = strategy.getPeers();
7777
this.unrespondedPeers = new Set(this.peers);
7878

79-
this.notificationPromise = new Promise((resolve, reject) => {
79+
this.notificationPromise = new Promise((resolve) => {
8080
this.resolveNotificationPromise = resolve;
81-
this.rejectNotificationPromise = reject;
8281
});
8382
}
8483

@@ -105,7 +104,10 @@ export class TransactionEventHandler implements TxEventHandler {
105104
*/
106105
async waitForEvents() :Promise<void> {
107106
logger.debug('waitForEvents start');
108-
await this.notificationPromise;
107+
const err = await this.notificationPromise;
108+
if (err) {
109+
throw err;
110+
}
109111
logger.debug('waitForEvents end');
110112
}
111113

@@ -196,6 +198,6 @@ export class TransactionEventHandler implements TxEventHandler {
196198
logger.warn('strategyFail: commit failure for transaction %j: %s', this.transactionId, error);
197199

198200
this.cancelListening();
199-
this.rejectNotificationPromise(error);
201+
this.resolveNotificationPromise(error);
200202
}
201203
}

fabric-network/test/impl/event/transactioneventhandler.spec.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,23 @@ describe('TransactionEventHandler', () => {
277277
await expect(promise).to.be.rejectedWith(/timeout/i);
278278
});
279279

280+
it('no unhandled rejection if timeout before waitForEvents() called', async () => {
281+
let unhandledRejectionErr: unknown;
282+
const listener = (err:unknown) => unhandledRejectionErr = err;
283+
process.on('unhandledRejection', listener);
284+
try {
285+
options.eventHandlerOptions = {commitTimeout: 0.01};
286+
handler = new TransactionEventHandler(transactionId, network, strategy);
287+
await handler.startListening();
288+
await clock.runAllAsync();
289+
const promise = handler.waitForEvents();
290+
await expect(promise).to.be.rejectedWith(/timeout/i);
291+
expect(unhandledRejectionErr).to.be.undefined;
292+
} finally {
293+
process.removeListener('unhandledRejection', listener);
294+
}
295+
});
296+
280297
it('does not timeout if timeout set to zero', async () => {
281298
stubStrategy.eventReceived.callsArg(0);
282299
options.eventHandlerOptions = {commitTimeout: 0};

test/ts-scenario/config/handlers/sample-transaction-event-handler.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,8 @@ import {Endorser} from 'fabric-common';
2626
class SampleTransactionEventHandler implements TxEventHandler {
2727
private readonly network: Network;
2828
private readonly transactionId: string;
29-
private readonly notificationPromise: Promise<unknown>;
30-
private resolveNotificationPromise!: (value?: unknown) => void;
31-
private rejectNotificationPromise!: (reason: Error) => void;
29+
private readonly notificationPromise: Promise<Error | undefined>;
30+
private resolveNotificationPromise!: (err?: Error) => void;
3231
private timeoutHandler?: NodeJS.Timeout;
3332
private readonly listener: CommitListener = this.eventCallback.bind(this);
3433
private readonly peers: Endorser[];
@@ -48,9 +47,8 @@ class SampleTransactionEventHandler implements TxEventHandler {
4847
this.peers = peers;
4948
this.unrespondedPeers = new Set(peers);
5049

51-
this.notificationPromise = new Promise((resolve, reject) => {
50+
this.notificationPromise = new Promise((resolve) => {
5251
this.resolveNotificationPromise = resolve;
53-
this.rejectNotificationPromise = reject;
5452
});
5553
}
5654

@@ -67,7 +65,10 @@ class SampleTransactionEventHandler implements TxEventHandler {
6765
* @throws {Error} if the transaction commit fails or is not successful within the timeout period.
6866
*/
6967
async waitForEvents() {
70-
await this.notificationPromise;
68+
const err = await this.notificationPromise;
69+
if (err) {
70+
throw err;
71+
}
7172
}
7273

7374
/**
@@ -103,7 +104,7 @@ class SampleTransactionEventHandler implements TxEventHandler {
103104

104105
private fail(error: Error) {
105106
this.cancelListening();
106-
this.rejectNotificationPromise(error);
107+
this.resolveNotificationPromise(error);
107108
}
108109

109110
private success() {
@@ -122,4 +123,4 @@ export const createTransactionEventHandler: TxEventHandlerFactory = (transaction
122123
const mspId = network.getGateway().getIdentity().mspId;
123124
const peers = network.getChannel().getEndorsers(mspId);
124125
return new SampleTransactionEventHandler(transactionId, network, peers);
125-
};
126+
};

0 commit comments

Comments
 (0)