Skip to content

Commit

Permalink
feat: update tests and cache to fit multi-fids querying
Browse files Browse the repository at this point in the history
  • Loading branch information
Complexlity committed Sep 3, 2024
1 parent 3b9f776 commit f8388b1
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 45 deletions.
20 changes: 5 additions & 15 deletions src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,24 +141,19 @@ describe("main cache", () => {

test("should use cache for getUsersByFid", async () => {
mockService.getUsersByFid.mockResolvedValueOnce({
data: mockUser,
data: [mockUser, mockUser],
error: null,
});

// First call should hit the service
const result1 = await sdk.getUsersByFid([mockUser.fid]);
expect(result1.data).toEqual(mockUser);
const result1 = await sdk.getUsersByFid([mockUser.fid, mockUser.fid]);
expect(result1.data).toEqual([mockUser, mockUser]);
expect(mockService.getUsersByFid).toHaveBeenCalledTimes(1);

// Second call should use cache
const result2 = await sdk.getUsersByFid([mockUser.fid]);
expect(result2.data).toEqual(mockUser);
const result2 = await sdk.getUsersByFid([mockUser.fid, mockUser.fid]);
expect(result2.data).toEqual([mockUser, mockUser]);
expect(mockService.getUsersByFid).toHaveBeenCalledTimes(1); // Still 1, not 2

// Second call should use cache
const result3 = await sdk.getUserByUsername(mockUser.username);
expect(result3.data).toEqual(mockUser);
expect(mockService.getUserByUsername).not.toBeCalled(); // Still 1, not 2
});

test("should use cache for getUserByUsername", async () => {
Expand All @@ -176,11 +171,6 @@ describe("main cache", () => {
const result2 = await sdk.getUserByUsername(mockUser.username);
expect(result2.data).toEqual(mockUser);
expect(mockService.getUserByUsername).toHaveBeenCalledTimes(1); // Still 1, not 2

// Third call with fid should still use cache
const result3 = await sdk.getUsersByFid([mockUser.fid]);
expect(result3.data).toEqual(mockUser);
expect(mockService.getUsersByFid).not.toBeCalled();
});

test("should use cache for getCastByHash", async () => {
Expand Down
8 changes: 4 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,8 @@ class uniFarcasterSdk implements Omit<Service, "name" | "customQuery"> {
);
const { data } = result;
if (data) {
//First params is the fid or username and we don't want to add that since we would get that from data
const setParams = type === "custom" ? params : params.slice(1);
//First params is the either hash or url and we don't want to add that since we would get that from data
const setParams = type === "cast" ? params.slice(1) : params;
this.cache.set(type, data, setParams);
}
return result;
Expand Down Expand Up @@ -309,7 +309,7 @@ class uniFarcasterSdk implements Omit<Service, "name" | "customQuery"> {
}

public async getUsersByFid(fids: number[], viewerFid: number = DEFAULTS.fid) {
const res = (await this.withCache("user", "getUsersByFid", [
const res = (await this.withCache("fid", "getUsersByFid", [
fids,
viewerFid,
])) as DataOrError<User[]>;
Expand All @@ -320,7 +320,7 @@ class uniFarcasterSdk implements Omit<Service, "name" | "customQuery"> {
username: string,
viewerFid: number = DEFAULTS.fid,
) {
const res = await this.withCache("user", "getUserByUsername", [
const res = await this.withCache("username", "getUserByUsername", [
username,
viewerFid,
]);
Expand Down
50 changes: 35 additions & 15 deletions src/lib/cache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,23 @@ describe("cache", () => {
cache = new Cache();
});

test("should set and get user data", () => {
test("should set and get user data by fid", () => {
const user: User = dummyUser;

cache.set("user", user, [dummyViewerFid]);
cache.set("fid", [user, user], [[user.fid, user.fid], dummyViewerFid]);

const cachedUserByFid = cache.get("user", [user.fid, dummyViewerFid]);
expect(cachedUserByFid).toEqual(user);
const cachedUserByFid = cache.get("fid", [
[user.fid, user.fid],
dummyViewerFid,
]);
expect(cachedUserByFid).toEqual([user, user]);
});
test("should set and get user data by username", () => {
const user: User = dummyUser;

cache.set("username", user, [user.username, dummyViewerFid]);

const cachedUserByUsername = cache.get("user", [
const cachedUserByUsername = cache.get("username", [
user.username,
dummyViewerFid,
]);
Expand All @@ -71,8 +79,10 @@ describe("cache", () => {
});

test("should return null for non-existent data", () => {
const nonExistentUser = cache.get("user", ["nonexistent"]);
const nonExistentUser = cache.get("username", ["nonexistent"]);
expect(nonExistentUser).toBeNull();
const nonExistentUser2 = cache.get("fid", [[124], 213144]);
expect(nonExistentUser2).toBeNull();

const nonExistentCast = cache.get("cast", ["nonexistent"]);
expect(nonExistentCast).toBeNull();
Expand Down Expand Up @@ -106,12 +116,15 @@ describe("cache with custom TTL", () => {
const cache = new Cache({ ttl: 0 });
const user: User = dummyUser;

cache.set("user", user, [dummyViewerFid]);
cache.set("username", user, [user.username, dummyViewerFid]);

const cachedUserByFid = cache.get("user", [user.fid, dummyViewerFid]);
const cachedUserByFid = cache.get("username", [
user.username,
dummyViewerFid,
]);
expect(cachedUserByFid).toBeNull();

const cachedUserByUsername = cache.get("user", [
const cachedUserByUsername = cache.get("username", [
user.username,
dummyViewerFid,
]);
Expand All @@ -123,12 +136,16 @@ describe("cache with custom TTL", () => {
const cache = new Cache({ ttl: cacheTtl });
const user: User = dummyUser;

cache.set("user", user, [dummyViewerFid]);
cache.set("fid", [user, user], [[user.fid, user.fid], dummyViewerFid]);

const cachedUserByFid = cache.get("user", [user.fid, dummyViewerFid]);
expect(cachedUserByFid).toEqual(user);
const cachedUserByFid = cache.get("fid", [
[user.fid, user.fid],
dummyViewerFid,
]);
expect(cachedUserByFid).toEqual([user, user]);

const cachedUserByUsername = cache.get("user", [
cache.set("username", user, [user.username, dummyViewerFid]);
const cachedUserByUsername = cache.get("username", [
user.username,
dummyViewerFid,
]);
Expand All @@ -137,10 +154,13 @@ describe("cache with custom TTL", () => {
// Wait for cache to expire
await new Promise((resolve) => setTimeout(resolve, cacheTtl + 10));

const cachedUserByFid2 = cache.get("user", [user.fid, dummyViewerFid]);
const cachedUserByFid2 = cache.get("fid", [
[user.fid, user.fid],
dummyViewerFid,
]);
expect(cachedUserByFid2).toBeNull();

const cachedUserByUsername2 = cache.get("user", [
const cachedUserByUsername2 = cache.get("username", [
user.username,
dummyViewerFid,
]);
Expand Down
33 changes: 22 additions & 11 deletions src/lib/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,13 @@ export class Cache {
const cacheKey = `${["custom", ...params].join(":")}`;
return this.getData<unknown>(cacheKey) as unknown | null;
}
private setUserCachedData(data: User, params: UnknownArray) {
const fidKey = `${["user", data.fid, ...params].join(":")}`;
const usernameKey = `${["user", data.username, ...params].join(":")}`;
private setUserCachedData(
data: User | UserWithOptionalViewerContext | User[],
params: UnknownArray,
) {
const cacheKey = `${["user", ...params].join(":")}`;
const setData = { data, timestamp: Date.now() };
this.cache.set(fidKey, setData);
this.cache.set(usernameKey, setData);
this.cache.set(cacheKey, setData);
return data;
}
private setCastCachedData(data: Cast, params: UnknownArray): Cast {
Expand All @@ -75,8 +76,9 @@ export class Cache {
}

public get<T extends CacheKeys>(type: T, params: UnknownArray) {
if (type === "user") {
return this.getUserCachedData(params) as T extends "user"
if (type === "fid" || type === "username") {
const striginfiedParams = params.map((param) => JSON.stringify(param));
return this.getUserCachedData(striginfiedParams) as T extends "user"
? User | UserWithOptionalViewerContext | null
: never;
}
Expand All @@ -100,12 +102,20 @@ export class Cache {
data: CacheTypes[T],
params: UnknownArray,
): User | Cast | unknown {
if (type === "user") {
return this.setUserCachedData(data as User, params);
}
if (type === "cast") {
return this.setCastCachedData(data as Cast, params);
}
if (type === "username") {
const striginfiedParams = params.map((param) => JSON.stringify(param));
return this.setUserCachedData(
data as User | UserWithOptionalViewerContext,
striginfiedParams,
);
}
if (type === "fid") {
const striginfiedParams = params.map((param) => JSON.stringify(param));
return this.setUserCachedData(data as User[], striginfiedParams);
}
if (type === "custom") {
const striginfiedParams = params.map((param) => JSON.stringify(param));
return this.setCustomCachedData(data as unknown, striginfiedParams);
Expand All @@ -120,7 +130,8 @@ type CacheConfig = {
};

export type CacheTypes = {
user: User | UserWithOptionalViewerContext;
fid: User[];
username: User | UserWithOptionalViewerContext;
cast: Cast;
custom: unknown;
};
Expand Down
1 change: 1 addition & 0 deletions src/services/airstack/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ export class airstackService implements Service {
return { data, error };
}
const returnedData = data;
console.log(returnedData);
return { data: this.getCastFromAirstackResult(returnedData), error: null };
}

Expand Down

0 comments on commit f8388b1

Please sign in to comment.