Skip to content

Commit 5c991dc

Browse files
authored
Usage of Shared Cache for Synthetic transaction receipts (#1729)
* - Refactored getBlock and eth_getTransactionReceipt to use Shared Cache when working with synthetic receipts for HTS transactions. - Added Unit Tests where needed. Signed-off-by: Alfredo Gutierrez <[email protected]> * - Fix tests Signed-off-by: Alfredo Gutierrez <[email protected]> --------- Signed-off-by: Alfredo Gutierrez <[email protected]>
1 parent f128c3c commit 5c991dc

File tree

4 files changed

+79
-3
lines changed

4 files changed

+79
-3
lines changed

packages/relay/src/lib/eth.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,7 +1745,11 @@ export class EthImpl implements Eth {
17451745
}
17461746

17471747
const cacheKeySyntheticLog = `${constants.CACHE_KEY.SYNTHETIC_LOG_TRANSACTION_HASH}${hash}`;
1748-
const cachedLog = this.cacheService.get(cacheKeySyntheticLog, EthImpl.ethGetTransactionReceipt, requestIdPrefix);
1748+
const cachedLog = await this.cacheService.getSharedWithFallback(
1749+
cacheKeySyntheticLog,
1750+
EthImpl.ethGetTransactionReceipt,
1751+
requestIdPrefix,
1752+
);
17491753
if (cachedLog) {
17501754
const receipt: any = {
17511755
blockHash: cachedLog.blockHash,
@@ -2000,15 +2004,29 @@ export class EthImpl implements Eth {
20002004
transactionArray.push(transaction);
20012005

20022006
const cacheKey = `${constants.CACHE_KEY.SYNTHETIC_LOG_TRANSACTION_HASH}${log.transactionHash}`;
2003-
this.cacheService.set(cacheKey, log, EthImpl.ethGetBlockByHash, this.syntheticLogCacheTtl, requestIdPrefix);
2007+
this.cacheService.set(
2008+
cacheKey,
2009+
log,
2010+
EthImpl.ethGetBlockByHash,
2011+
this.syntheticLogCacheTtl,
2012+
requestIdPrefix,
2013+
true,
2014+
);
20042015
});
20052016
} else {
20062017
filteredLogs = logs.filter((log) => !transactionArray.includes(log.transactionHash));
20072018
filteredLogs.forEach((log) => {
20082019
transactionArray.push(log.transactionHash);
20092020

20102021
const cacheKey = `${constants.CACHE_KEY.SYNTHETIC_LOG_TRANSACTION_HASH}${log.transactionHash}`;
2011-
this.cacheService.set(cacheKey, log, EthImpl.ethGetBlockByHash, this.syntheticLogCacheTtl, requestIdPrefix);
2022+
this.cacheService.set(
2023+
cacheKey,
2024+
log,
2025+
EthImpl.ethGetBlockByHash,
2026+
this.syntheticLogCacheTtl,
2027+
requestIdPrefix,
2028+
true,
2029+
);
20122030
});
20132031

20142032
this.logger.trace(

packages/relay/src/lib/services/cacheService/cacheService.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,21 @@ export class CacheService {
148148
}
149149
}
150150

151+
/**
152+
* If SharedCacheEnabled will use shared, otherwise will fallback to internal cache.
153+
* @param {string} key - The cache key.
154+
* @param {string} callingMethod - The name of the calling method.
155+
* @param {string} [requestIdPrefix] - The optional request ID prefix.
156+
* @returns {Promise<any>} A Promise that resolves with the cached value or null if not found.
157+
*/
158+
public getSharedWithFallback(key: string, callingMethod: string, requestIdPrefix?: string): any {
159+
if (this.isSharedCacheEnabled) {
160+
return this.getAsync(key, callingMethod, requestIdPrefix);
161+
} else {
162+
return this.get(key, callingMethod, requestIdPrefix);
163+
}
164+
}
165+
151166
/**
152167
* Retrieves a value from the internal cache.
153168
*

packages/relay/tests/lib/ethGetBlockBy.spec.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import HbarLimit from '../../src/lib/hbarlimiter';
3434
import { Log, Transaction } from '../../src/lib/model';
3535
import { nullableNumberTo0x, numberTo0x, nanOrNumberTo0x, toHash32 } from '../../../../packages/relay/src/formatters';
3636
import { CacheService } from '../../src/lib/services/cacheService/cacheService';
37+
import * as sinon from 'sinon';
3738

3839
const LRU = require('lru-cache');
3940

@@ -260,6 +261,7 @@ const defaultNetworkFees = {
260261
describe('eth_getBlockBy', async function () {
261262
this.timeout(10000);
262263
let ethImpl: EthImpl;
264+
const sandbox = sinon.createSandbox();
263265

264266
this.beforeAll(() => {
265267
cacheService = new CacheService(logger.child({ name: `cache` }), registry);
@@ -294,6 +296,11 @@ describe('eth_getBlockBy', async function () {
294296
// reset cache and restMock
295297
cacheService.clear();
296298
restMock.reset();
299+
sandbox.spy(cacheService, 'set');
300+
});
301+
302+
afterEach(function () {
303+
sandbox.restore();
297304
});
298305

299306
const mirrorLogToModelLog = (mirrorLog) => {
@@ -432,6 +439,18 @@ describe('eth_getBlockBy', async function () {
432439
const cacheKeySyntheticLog2 = `${constants.CACHE_KEY.SYNTHETIC_LOG_TRANSACTION_HASH}${modelLog2.transactionHash}`;
433440
const cacheKeySyntheticLog3 = `${constants.CACHE_KEY.SYNTHETIC_LOG_TRANSACTION_HASH}${modelLog3.transactionHash}`;
434441

442+
function verifySharedCacheWasUsed() {
443+
// verify shared cache was selected
444+
const txCount = referenceLogs.length;
445+
// @ts-ignore - spy
446+
expect(cacheService.set.callCount).to.equal(txCount);
447+
// @ts-ignore - spy
448+
for (let i = 0; i < txCount; i++) {
449+
// @ts-ignore - spy
450+
expect(cacheService.set.getCall(i).args[5], 'shared cache should be used').to.equal(true);
451+
}
452+
}
453+
435454
it('filterAndPopulateSyntheticContractResults showDetails=false sets cache', async function () {
436455
expect(cacheService.get(cacheKeySyntheticLog1, '', '')).to.be.null;
437456
expect(cacheService.get(cacheKeySyntheticLog2, '', '')).to.be.null;
@@ -442,6 +461,7 @@ describe('eth_getBlockBy', async function () {
442461
expect(cacheService.get(cacheKeySyntheticLog1, '', '')).to.be.equal(modelLog1);
443462
expect(cacheService.get(cacheKeySyntheticLog2, '', '')).to.be.equal(modelLog2);
444463
expect(cacheService.get(cacheKeySyntheticLog3, '', '')).to.be.equal(modelLog3);
464+
verifySharedCacheWasUsed();
445465
});
446466

447467
it('filterAndPopulateSyntheticContractResults showDetails=true sets cache', async function () {
@@ -454,6 +474,7 @@ describe('eth_getBlockBy', async function () {
454474
expect(cacheService.get(cacheKeySyntheticLog1, '', '')).to.be.equal(modelLog1);
455475
expect(cacheService.get(cacheKeySyntheticLog2, '', '')).to.be.equal(modelLog2);
456476
expect(cacheService.get(cacheKeySyntheticLog3, '', '')).to.be.equal(modelLog3);
477+
verifySharedCacheWasUsed();
457478
});
458479
});
459480
});

packages/relay/tests/lib/services/cacheService/cacheService.spec.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,16 @@ describe('CacheService Test Suite', async function () {
6666

6767
expect(cachedValue).to.be.null;
6868
});
69+
70+
it('should be able to get from internal cache when calling getSharedWithFallback', async function () {
71+
const key = 'string';
72+
const value = 'value';
73+
74+
cacheService.set(key, value, callingMethod, undefined, undefined, true);
75+
const cachedValue = cacheService.getSharedWithFallback(key, callingMethod);
76+
77+
expect(cachedValue).eq(value);
78+
});
6979
});
7080

7181
describe('Shared Cache Test Suite', async function () {
@@ -109,5 +119,17 @@ describe('CacheService Test Suite', async function () {
109119

110120
expect(cachedValue).to.be.null;
111121
});
122+
123+
it('should be able to get from shared cache with fallback to internal cache', async function () {
124+
const key = 'string';
125+
const value = 'value';
126+
127+
cacheService.set(key, value, callingMethod, undefined, undefined, true);
128+
129+
mock.stub(cacheService, 'getAsync').returns(value);
130+
const cachedValue = await cacheService.getSharedWithFallback(key, callingMethod, undefined);
131+
132+
expect(cachedValue).eq(value);
133+
});
112134
});
113135
});

0 commit comments

Comments
 (0)