Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: leveldb cache perfomance #257

Merged
merged 2 commits into from
Oct 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/contracts/deposits-registry/deposits-registry.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class DepositRegistryService {

public async initialize() {
await this.store.initialize();
const cachedEvents = await this.store.getEventsCache();
const cachedEvents = this.store.getEventsCache();
await this.sanityChecker.initialize(cachedEvents);

await this.updateEventsCache();
Expand All @@ -49,7 +49,7 @@ export class DepositRegistryService {
* @returns event group
*/
public async getCachedEvents(): Promise<VerifiedDepositEventsCache> {
const { headers, ...rest } = await this.store.getEventsCache();
const { headers, ...rest } = this.store.getEventsCache();
const deploymentBlock = await this.fetcher.getDeploymentBlockByNetwork();

return {
Expand Down
16 changes: 11 additions & 5 deletions src/contracts/deposits-registry/store/store.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ import { PrometheusModule } from 'common/prometheus';
const getEventsDepositCount = async (
dbService: DepositsRegistryStoreService,
) => {
const result = await dbService.getEventsCache();
const expectedDeposits = result.data.map((event) => event.depositCount);
const resultCache = dbService.getEventsCache();
const resultDB = await dbService.getEventsFromDB();

expect(resultCache).toEqual(resultDB);
const expectedDeposits = resultCache.data.map((event) => event.depositCount);
return expectedDeposits;
};

Expand Down Expand Up @@ -46,17 +49,20 @@ describe('dbService', () => {
});

it('should return default cache', async () => {
const result = await dbService.getEventsCache();
const result = dbService.getEventsCache();
expect(result).toEqual(defaultCacheValue);
});

it('should return saved cache', async () => {
const expected = cacheMock;

await dbService.insertEventsCacheBatch(expected);
const result = await dbService.getEventsCache();

expect(result).toEqual(expected);
const resultCache = await dbService.getEventsCache();
const resultDB = await dbService.getEventsFromDB();

expect(resultCache).toEqual(resultDB);
expect(resultCache).toEqual(expected);
});

describe('deleteDepositsGreaterThanNBatch', () => {
Expand Down
43 changes: 40 additions & 3 deletions src/contracts/deposits-registry/store/store.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { Histogram } from 'prom-client';
@Injectable()
export class DepositsRegistryStoreService {
private db!: Level<string, string>;
private cache!: VerifiedDepositEventsCache;
constructor(
private providerService: ProviderService,
@InjectMetric(METRIC_JOB_DURATION)
Expand All @@ -35,6 +36,7 @@ export class DepositsRegistryStoreService {

public async initialize() {
await this.setupLevel();
await this.setupEventsCache();
}

/**
Expand All @@ -50,6 +52,23 @@ export class DepositsRegistryStoreService {
await this.db.open();
}

/**
* Initializes or updates the event cache by fetching events from the database.
* This method asynchronously sets the `this.cache` property with the event data obtained from the database.
*/
private async setupEventsCache(): Promise<void> {
this.cache = await this.getEventsFromDB();
}

/**
* Returns a default value for the cache by deep cloning the predefined default cache value.
* This method uses JSON serialization to ensure a deep clone of `this.cacheDefaultValue`.
* @returns {VerifiedDepositEventsCache} A deep cloned copy of the default cache value.
*/
private getDefaultCachedValue(): VerifiedDepositEventsCache {
return JSON.parse(JSON.stringify(this.cacheDefaultValue));
}

/**
* Fetches and constructs the cache directory path for the current blockchain network.
*
Expand All @@ -71,14 +90,14 @@ export class DepositsRegistryStoreService {
* @returns {Promise<{data: VerifiedDepositEvent[], headers: VerifiedDepositEventsCacheHeaders}>} Cache data and headers.
* @public
*/
public async getEventsCache(): Promise<{
public async getEventsFromDB(): Promise<{
data: VerifiedDepositEvent[];
headers: VerifiedDepositEventsCacheHeaders;
lastValidEvent?: VerifiedDepositEvent;
}> {
const endTimer = this.jobDurationMetric
.labels({
jobName: 'getEventsCache_deposits',
jobName: 'getEventsCache_deposits_db',
})
.startTimer();

Expand All @@ -98,13 +117,22 @@ export class DepositsRegistryStoreService {

return { data, headers, lastValidEvent };
} catch (error: any) {
if (error.code === 'LEVEL_NOT_FOUND') return this.cacheDefaultValue;
if (error.code === 'LEVEL_NOT_FOUND') return this.getDefaultCachedValue();
throw error;
} finally {
endTimer();
}
}

/**
* Retrieves the current event cache.
* This method returns the cache of events which includes verified deposit events.
* @returns {VerifiedDepositEventsCache} The current event cache.
*/
public getEventsCache(): VerifiedDepositEventsCache {
return this.cache;
}

/**
* Retrieves the last valid deposit event from the database.
* This method queries the database for the 'last-valid-event' key to fetch the most recent
Expand Down Expand Up @@ -169,6 +197,7 @@ export class DepositsRegistryStoreService {
// Execute the batch operation if there are any operations to perform
if (ops.length > 0) {
await this.db.batch(ops);
await this.setupEventsCache();
}
}

Expand Down Expand Up @@ -250,6 +279,9 @@ export class DepositsRegistryStoreService {
value: JSON.stringify(records.headers),
});
await this.db.batch(ops);

this.cache.data = this.cache.data.concat(records.data);
this.cache.headers = { ...records.headers };
}

/**
Expand All @@ -261,6 +293,7 @@ export class DepositsRegistryStoreService {
*/
public async insertLastValidEvent(event: VerifiedDepositEvent) {
await this.db.put('last-valid-event', this.serializeDepositEvent(event));
this.cache.lastValidEvent = event;
}

/**
Expand All @@ -271,6 +304,7 @@ export class DepositsRegistryStoreService {
*/
public async deleteCache(): Promise<void> {
await this.db.clear();
this.cache = this.getDefaultCachedValue();
}

/**
Expand All @@ -296,5 +330,8 @@ export class DepositsRegistryStoreService {
...cachedEvents.headers,
},
});

this.cache.data = this.cache.data.concat(cachedEvents.data);
this.cache.headers = { ...cachedEvents.headers };
}
}
Loading