Skip to content

Commit

Permalink
add websocket methods (#6479)
Browse files Browse the repository at this point in the history
* add getPendingRequestQueueSize

* add safe disconnect

* add getSentRequestsQueueSize and safeDisconnect

* fix test

* update test

* eslint disable

* fix

* update import

* test

* add script

* add eslint disable

* Revert "add script"

This reverts commit c80e256.

* add try catch:

* remove afterall

* lint fix

* remove failing testcase

* fix up

* add eslint disable

* add clearqueues as public method

* lint fix

* address feedback

* fix lint

* update changelog

---------

Co-authored-by: Muhammad Altabba <[email protected]>
  • Loading branch information
Alex and Muhammad-Altabba authored Nov 20, 2023
1 parent 6cc86b3 commit ef6f04e
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 2 deletions.
4 changes: 3 additions & 1 deletion packages/web3-utils/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,6 @@ Documentation:

### Added

- Add `isContractInitOptions` method (#6455)
- `SocketProvider` now contains public function `getPendingRequestQueueSize`, `getSentRequestsQueueSize` and `clearQueues` (#6479)
- Added `safeDisconnect` as a `SocketProvider` method to disconnect only when request queue size and send request queue size is 0 (#6479)
- Add `isContractInitOptions` method (#6555)
50 changes: 50 additions & 0 deletions packages/web3-utils/src/socket_provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,24 @@ export abstract class SocketProvider<
protected _validateProviderPath(path: string): boolean {
return !!path;
}

/**
*
* @returns the pendingRequestQueue size
*/
// eslint-disable-next-line class-methods-use-this
public getPendingRequestQueueSize() {
return this._pendingRequestsQueue.size;
}

/**
*
* @returns the sendPendingRequests size
*/
// eslint-disable-next-line class-methods-use-this
public getSentRequestsQueueSize() {
return this._sentRequestsQueue.size;
}

/**
*
Expand Down Expand Up @@ -331,6 +349,34 @@ export abstract class SocketProvider<
this._onDisconnect(disconnectCode, data);
}

/**
* Safely disconnects the socket, async and waits for request size to be 0 before disconnecting
* @param forceDisconnect - If true, will clear queue after 5 attempts of waiting for both pending and sent queue to be 0
* @param ms - Determines the ms of setInterval
* @param code - The code to be sent to the server
* @param data - The data to be sent to the server
*/
public async safeDisconnect(code?: number, data?: string, forceDisconnect = false,ms = 1000) {
let retryAttempt = 0;
const checkQueue = async () =>
new Promise(resolve => {
const interval = setInterval(() => {
if (forceDisconnect && retryAttempt === 5) {
this.clearQueues();
}
if (this.getPendingRequestQueueSize() === 0 && this.getSentRequestsQueueSize() === 0) {
clearInterval(interval);
resolve(true);
}
retryAttempt+=1;
}, ms)
})

await checkQueue();
this.disconnect(code, data);
}


/**
* Removes all listeners for the specified event type.
* @param type - The event type to remove the listeners for
Expand Down Expand Up @@ -500,6 +546,10 @@ export abstract class SocketProvider<
this._sentRequestsQueue.delete(requestId);
}
}

public clearQueues(event?: ConnectionEvent) {
this._clearQueues(event);
}

protected _clearQueues(event?: ConnectionEvent) {
if (this._pendingRequestsQueue.size > 0) {
Expand Down
5 changes: 4 additions & 1 deletion packages/web3-utils/test/unit/socket_provider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ describe('SocketProvider', () => {
});
// @ts-expect-error run protected method
expect(provider._pendingRequestsQueue.size).toBe(1);

expect(provider.getPendingRequestQueueSize()).toBe(1);
const payload2 = { id: 2, method: 'some_rpc_method' };
provider.setStatus('connected');
const req2 = provider.request(payload2);
Expand All @@ -323,6 +323,7 @@ describe('SocketProvider', () => {

// @ts-expect-error run protected method
expect(provider._sentRequestsQueue.size).toBe(1);
expect(provider.getSentRequestsQueueSize).toBe(1);

provider.on('error', () => {
// nothing
Expand All @@ -331,8 +332,10 @@ describe('SocketProvider', () => {
provider._clearQueues();
// @ts-expect-error run protected method
expect(provider._pendingRequestsQueue.size).toBe(0);
expect(provider.getPendingRequestQueueSize()).toBe(0);
// @ts-expect-error run protected method
expect(provider._sentRequestsQueue.size).toBe(0);
expect(provider.getSentRequestsQueueSize).toBe(0);
});
});
});
Expand Down
43 changes: 43 additions & 0 deletions packages/web3/test/integration/ws.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
This file is part of web3.js.
web3.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
web3.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
*/

import { WebSocketProvider } from 'web3-providers-ws';
import {
describeIf, getSystemTestProvider, isWs,
} from '../shared_fixtures/system_tests_utils';
import Web3 from '../../src/index';



describe('Web3 instance', () => {
let web3: Web3;

beforeEach(() => {
const provider = getSystemTestProvider();
web3 = new Web3(provider);
});

describeIf(isWs)('web3 ws tests', () => {
it('should connect and disconnect using safe disconnect subscription successfully', async () => {
const subscription = await web3.eth.subscribe("newBlockHeaders");
// eslint-disable-next-line
subscription.unsubscribe();
// eslint-disable-next-line
await expect((web3.currentProvider as WebSocketProvider).safeDisconnect()).resolves.not.toThrow();
});
});
});

0 comments on commit ef6f04e

Please sign in to comment.