Skip to content

Commit

Permalink
Use redis as a caching layer
Browse files Browse the repository at this point in the history
  • Loading branch information
Inkvi committed Mar 12, 2024
1 parent a2c3b68 commit 63d962f
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 24 deletions.
2 changes: 1 addition & 1 deletion app/api/cache/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export async function GET(request: NextRequest) {
try {
const packets = await getPackets();
console.log("Saving packets to cache");
cache.set('allPackets', packets, getCacheTTL());
await cache.set('allPackets', packets, -1);
return NextResponse.json(packets);
} catch (e) {
console.error('Error fetching packets', e);
Expand Down
2 changes: 1 addition & 1 deletion app/api/packets/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,6 @@ export async function getPackets() {

export async function GET(request: NextRequest) {
const cache = SimpleCache.getInstance();
const allPackets = cache.get('allPackets');
const allPackets = await cache.get('allPackets');
return NextResponse.json(allPackets || []);
}
39 changes: 24 additions & 15 deletions app/api/utils/cosmos.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,44 @@
import { IbcExtension, QueryClient, setupIbcExtension } from '@cosmjs/stargate';
import { Tendermint37Client } from '@cosmjs/tendermint-rpc';
import NodeCache from 'node-cache';
import Redis from 'ioredis';
import { Height } from 'cosmjs-types/ibc/core/client/v1/client';
import * as process from 'process';

interface ICache {
get<T>(key: string): T | undefined;
set<T>(key: string, value: T, ttl: number): void;
get<T>(key: string): Promise<T | null>;
set<T>(key: string, value: T, ttl?: number): Promise<void>;
}

export class SimpleCache implements ICache {
private static instance: SimpleCache;
private cache: NodeCache;
private redis: Redis;

private constructor(defaultTTL: number) {
this.cache = new NodeCache({ stdTTL: defaultTTL });
private constructor() {
this.redis = new Redis(); // Default connects to 127.0.0.1:6379
}

public static getInstance(defaultTTL: number = getCacheTTL()): SimpleCache {
public static getInstance(): SimpleCache {
if (!SimpleCache.instance) {
SimpleCache.instance = new SimpleCache(defaultTTL);
SimpleCache.instance = new SimpleCache();
}
return SimpleCache.instance;
}

get<T>(key: string): T | undefined {
return this.cache.get(key);
async get<T>(key: string): Promise<T | null> {
const value = await this.redis.get(key);
return value ? JSON.parse(value) as T : null;
}

set<T>(key: string, value: T, ttl: number = 0): void {
this.cache.set(key, value, ttl);
async set<T>(key: string, value: T, ttl: number = getCacheTTL()): Promise<void> {
const stringValue = JSON.stringify(value, (_key, val) =>
typeof val === 'bigint' ? val.toString() : val // Convert BigInt to string
);
// if ttl is set to -1 then the key should never expire
if (ttl === -1) {
await this.redis.set(key, stringValue);
} else {
await this.redis.set(key, stringValue, 'EX', ttl);
}
}
}

Expand All @@ -38,14 +47,14 @@ class CachingIbcExtension {
private ttl: number;

constructor(private ibcExtension: IbcExtension, ttl: number = 60) {
this.cache = SimpleCache.getInstance(ttl);
this.cache = SimpleCache.getInstance();
this.ttl = ttl;
}

async cachedCall<T>(cacheKey: string, call: () => Promise<T>): Promise<T> {
let cachedResult: T | undefined = this.cache.get(cacheKey);
let cachedResult: T | null = await this.cache.get(cacheKey);

if (cachedResult !== undefined) {
if (cachedResult !== null) {
return cachedResult;
}

Expand Down
8 changes: 4 additions & 4 deletions app/api/utils/provider-cache.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { ethers } from 'ethers';
import * as flatCache from 'flat-cache';
import { SimpleCache } from '@/api/utils/cosmos';

export class CachingJsonRpcProvider extends ethers.JsonRpcProvider {
private cache;

constructor(url: string, network?: ethers.Networkish) {
super(url, network);
this.cache = flatCache.load('ethCache', "/tmp");
this.cache = SimpleCache.getInstance();
}

private async fetchDataWithCache<T>(cacheKey: string, fetchFunction: () => Promise<T>): Promise<T> {
// Check if the data is already in the cache
const cachedData = this.cache.getKey(cacheKey);
const cachedData = await this.cache.get<T>(cacheKey);
if (cachedData) {
return cachedData;
}
Expand All @@ -20,8 +21,7 @@ export class CachingJsonRpcProvider extends ethers.JsonRpcProvider {
const data = await fetchFunction();

// Store the new data in the cache
this.cache.setKey(cacheKey, data);
this.cache.save(true);
await this.cache.set(cacheKey, data);
return data;
}

Expand Down
83 changes: 80 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"@types/flat-cache": "^2.0.2",
"ethers": "^6.10.0",
"flat-cache": "^4.0.0",
"ioredis": "^5.3.2",
"next": "14.1.0",
"node-cache": "^5.1.2",
"plimit-lit": "^2.1.0",
Expand Down

0 comments on commit 63d962f

Please sign in to comment.