Skip to content

Commit 81e09f1

Browse files
feat: use subject dictionary to avoid creating multiple duplicated subscriptions (#67)
* feat: keep track of props subjects * Keep track of subjects for event and log trackers
1 parent 556bf51 commit 81e09f1

File tree

1 file changed

+46
-27
lines changed

1 file changed

+46
-27
lines changed

src/subspace.js

+46-27
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ReplaySubject, BehaviorSubject } from 'rxjs';
1+
import { ReplaySubject, BehaviorSubject, Subject } from 'rxjs';
22
import { distinctUntilChanged, map } from 'rxjs/operators';
33
import equal from 'fast-deep-equal';
44
import Database from './database/database.js';
@@ -10,6 +10,7 @@ import stripHexPrefix from 'strip-hex-prefix';
1010
import {hexToDec} from 'hex2dec';
1111
import EventSyncer from './eventSyncer';
1212
import LogSyncer from './logSyncer';
13+
import hash from 'object-hash';
1314

1415
export default class Subspace {
1516

@@ -30,19 +31,13 @@ export default class Subspace {
3031
this.networkId = undefined;
3132
this.isWebsocketProvider = options.disableSubscriptions ? false : !!provider.on;
3233

34+
// Stats
35+
this.latestBlockNumber = undefined;
36+
this.latestGasPrice = undefined;
37+
this.latestBlock = undefined;
38+
this.latest10Blocks = [];
3339

34-
// TODO: part of manager
35-
this.latestBlockNumber = undefined;
36-
this.latestGasPrice = undefined;
37-
this.latestBlock = undefined;
38-
this.latest10Blocks = [];
39-
40-
41-
// TODO: part of manager
42-
this.blockNumberObservable = null;
43-
this.gasPriceObservable = null;
44-
this.blockObservable = null;
45-
this.blockTimeObservable = null;
40+
this.subjects = {};
4641

4742
this.newBlocksSubscription = null;
4843
this.intervalTracker = null;
@@ -77,7 +72,7 @@ this.blockTimeObservable = null;
7772
this.latest10Blocks = await Promise.all(this.latest10Blocks);
7873
}
7974

80-
// TODO: part of manager
75+
// Initial stats
8176
this.latestBlockNumber = block.number;
8277
this.latestGasPrice = gasPrice;
8378
this.latestBlock = block;
@@ -149,9 +144,13 @@ this.blockTimeObservable = null;
149144
}
150145

151146
// TODO: get contract abi/address instead
152-
trackEvent(contractInstance, eventName, filterConditionsOrCb) {
147+
trackEvent(contractInstance, eventName, filterConditions) {
148+
const subjectHash = hash({address: contractInstance.options.address, networkId: this.networkId, eventName, filterConditions});
149+
150+
if(this.subjects[subjectHash]) return this.subjects[subjectHash];
151+
153152
let deleteFrom = this.latestBlockNumber - this.options.refreshLastNBlocks;
154-
let returnSub = this.eventSyncer.track(contractInstance, eventName, filterConditionsOrCb, deleteFrom, this.networkId);
153+
let returnSub = this.eventSyncer.track(contractInstance, eventName, filterConditions, deleteFrom, this.networkId);
155154

156155
returnSub.map = (prop) => {
157156
return returnSub.pipe(map((x) => {
@@ -168,6 +167,8 @@ this.blockTimeObservable = null;
168167
}))
169168
}
170169

170+
this.subjects[subjectHash] = returnSub;
171+
171172
return returnSub;
172173
}
173174

@@ -181,7 +182,14 @@ this.blockTimeObservable = null;
181182

182183
trackLogs(options, inputsABI) {
183184
if(!this.isWebsocketProvider) console.warn("This method only works with websockets");
184-
return this.logSyncer.track(options, inputsABI, this.latestBlockNumber - this.options.refreshLastNBlocks, this.networkId);
185+
186+
const subjectHash = hash({inputsABI, options});
187+
188+
if(this.subjects[subjectHash]) return this.subjects[subjectHash];
189+
190+
this.subjects[subjectHash] = this.logSyncer.track(options, inputsABI, this.latestBlockNumber - this.options.refreshLastNBlocks, this.networkId);
191+
192+
return this.subjects[subjectHash];
185193
}
186194

187195
_initNewBlocksSubscription() {
@@ -209,30 +217,34 @@ this.blockTimeObservable = null;
209217
}, this.options.callInterval);
210218
}
211219

212-
// TODO: should save value in database?
213220
trackProperty(contractInstance, propName, methodArgs = [], callArgs = {}) {
214-
const sub = new ReplaySubject();
221+
const subjectHash = hash({address: contractInstance.options.address, networkId: this.networkId, propName, methodArgs, callArgs});
222+
223+
if(this.subjects[subjectHash]) return this.subjects[subjectHash];
224+
225+
const subject = new Subject();
215226

216227
if (!Array.isArray(methodArgs)) {
217228
methodArgs = [methodArgs]
218229
}
219230

220-
const method = contractInstance.methods[propName].apply(contractInstance.methods[propName], methodArgs)
231+
const method = contractInstance.methods[propName].apply(contractInstance.methods[propName], methodArgs);
232+
221233
const callContractMethod = () => {
222234
method.call.apply(method.call, [callArgs, (err, result) => {
223235
if (err) {
224-
sub.error(err);
236+
subject.error(err);
225237
return;
226238
}
227-
sub.next(result);
239+
subject.next(result);
228240
}]);
229241
};
230242

231243
callContractMethod();
232244

233245
this.callables.push(callContractMethod);
234246

235-
let returnSub = sub.pipe(distinctUntilChanged((a, b) => equal(a, b)));
247+
const returnSub = subject.pipe(distinctUntilChanged((a, b) => equal(a, b)));
236248

237249
returnSub.map = (prop) => {
238250
return returnSub.pipe(map((x) => {
@@ -249,16 +261,23 @@ this.blockTimeObservable = null;
249261
}))
250262
}
251263

264+
this.subjects[subjectHash] = returnSub;
265+
252266
return returnSub;
253267
}
254268

255269
_addDistinctCallable(trackAttribute, cbBuilder, subject, subjectArg = undefined) {
256-
if(this[trackAttribute]) return this[trackAttribute].pipe(distinctUntilChanged((a, b) => equal(a, b)));
257-
this[trackAttribute] = new subject(subjectArg);
258-
const cb = cbBuilder(this[trackAttribute]);
270+
if(this.subjects[trackAttribute]) return this.subjects[trackAttribute];
271+
272+
const sub = new subject(subjectArg);
273+
274+
const cb = cbBuilder(sub);
259275
cb();
260276
this.callables.push(cb);
261-
return this[trackAttribute].pipe(distinctUntilChanged((a, b) => equal(a, b)));
277+
278+
this.subjects[trackAttribute] = sub.pipe(distinctUntilChanged((a, b) => equal(a, b)));
279+
280+
return this.subjects[trackAttribute];
262281
}
263282

264283
trackBlock() {

0 commit comments

Comments
 (0)