Skip to content

Commit

Permalink
♻️ refactor(cache): add domain to cache key
Browse files Browse the repository at this point in the history
  • Loading branch information
thrownullexception committed Dec 19, 2023
1 parent ee1d468 commit d775ccd
Show file tree
Hide file tree
Showing 9 changed files with 47 additions and 32 deletions.
17 changes: 11 additions & 6 deletions src/backend/lib/cache/AbstractCacheService.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ConfigDomain } from "../config-persistence/types";
import { ConfigApiService } from "../config/config.service";

export abstract class AbstractCacheService {
Expand All @@ -9,8 +10,8 @@ export abstract class AbstractCacheService {

public abstract setup(): Promise<void>;

private prefixKey(key: string) {
return `__dp__:${key}`;
private prefixKey(key: string, domain: ConfigDomain) {
return `__dp__:${domain}:${key}`;
}

protected abstract pullItem<T>(key: string): Promise<T | undefined>;
Expand All @@ -19,14 +20,18 @@ export abstract class AbstractCacheService {

protected abstract _clearItem(key: string): Promise<void>;

async clearItem(rawKey: string) {
await this._clearItem(this.prefixKey(rawKey));
async clearItem(rawKey: string, domain: ConfigDomain) {
await this._clearItem(this.prefixKey(rawKey, domain));
}

abstract purge(): Promise<void>;

async getItem<T>(rawKey: string, fetcher: () => Promise<T>) {
const key = this.prefixKey(rawKey);
async getItem<T>(
rawKey: string,
domain: ConfigDomain,
fetcher: () => Promise<T>
) {
const key = this.prefixKey(rawKey, domain);

const data = await this.pullItem<T>(key);

Expand Down
8 changes: 7 additions & 1 deletion src/backend/lib/cache/MemoryCacheAdaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@ export class MemoryCacheAdaptor extends AbstractCacheService {
}

async pullItem<T>(key: string): Promise<T | undefined> {
return MemoryCacheAdaptor.data[key] as T;
const data = MemoryCacheAdaptor.data[key] as T;

if (!data) {
return data;
}

return JSON.parse(JSON.stringify(data));
}

async persistData(key: string, data: unknown): Promise<void> {
Expand Down
12 changes: 6 additions & 6 deletions src/backend/lib/cache/__tests__/CacheAdaptor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ const CACHE_ADAPTORS: {
describe.each(CACHE_ADAPTORS)("$title cache adaptor", ({ adaptor }) => {
beforeAll(async () => {
await adaptor.setup();
await adaptor.clearItem("foo");
await adaptor.clearItem("foo", "temp-storage");
});

it("should call fetcher the first time", async () => {
const implementationMock = jest.fn();

const data = await adaptor.getItem("foo", async () => {
const data = await adaptor.getItem("foo", "temp-storage", async () => {
implementationMock();
return { foo: "bar" };
});
Expand All @@ -45,7 +45,7 @@ describe.each(CACHE_ADAPTORS)("$title cache adaptor", ({ adaptor }) => {
it("should not call fetcher the next time", async () => {
const implementationMock = jest.fn();

const data = await adaptor.getItem("foo", async () => {
const data = await adaptor.getItem("foo", "temp-storage", async () => {
implementationMock();
return { foo: "wrong-value" };
});
Expand All @@ -57,9 +57,9 @@ describe.each(CACHE_ADAPTORS)("$title cache adaptor", ({ adaptor }) => {
it("should call fetcher after clearing key", async () => {
const implementationMock = jest.fn();

await adaptor.clearItem("foo");
await adaptor.clearItem("foo", "temp-storage");

const data = await adaptor.getItem("foo", async () => {
const data = await adaptor.getItem("foo", "temp-storage", async () => {
implementationMock();
return { foo: "new-value" };
});
Expand All @@ -73,7 +73,7 @@ describe.each(CACHE_ADAPTORS)("$title cache adaptor", ({ adaptor }) => {

await adaptor.purge();

const data = await adaptor.getItem("foo", async () => {
const data = await adaptor.getItem("foo", "temp-storage", async () => {
implementationMock();
return { foo: "new-value" };
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,25 @@ export abstract class AbstractConfigDataPersistenceService<T> {
return `${key}__${secondaryKey}`;
}

public abstract _getItem(key: string): Promise<T | undefined>;
protected abstract _getItem(key: string): Promise<T | undefined>;

public abstract _persistItem(key: string, data: T): Promise<void>;
protected abstract _persistItem(key: string, data: T): Promise<void>;

public abstract _removeItem(key: string): Promise<void>;
protected abstract _removeItem(key: string): Promise<void>;

public async getItem(key: string) {
return await cacheService.getItem(key, async () => {
return this._getItem(key);
return await cacheService.getItem(key, this._configDomain, async () => {
return await this._getItem(key);
});
}

public async persistItem(key: string, data: T) {
await cacheService.clearItem(key);
await cacheService.clearItem(key, this._configDomain);
await this._persistItem(key, data);
}

public async removeItem(key: string) {
await cacheService.clearItem(key);
await cacheService.clearItem(key, this._configDomain);
await this._removeItem(key);
}

Expand Down Expand Up @@ -71,12 +71,16 @@ export abstract class AbstractConfigDataPersistenceService<T> {
}

public async resetState(keyField: keyof T, data: T[]) {
await cacheService.purge();
await this.resetToEmpty();
await this.saveAllItems(keyField, data);
}

protected abstract saveAllItems(keyField: keyof T, data: T[]): Promise<void>;

public abstract resetToEmpty(): Promise<void>;
public async resetToEmpty() {
await cacheService.purge();
await this._resetToEmpty();
}

protected abstract _resetToEmpty(): Promise<void>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export class DatabaseConfigDataPersistenceAdaptor<
await this.getDbInstance();
}

async resetToEmpty() {
async _resetToEmpty() {
await (await this.getDbInstance())(CONFIG_TABLE_NAME)
.where("domain", "=", this._configDomain)
.del();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class JsonFileConfigDataPersistenceAdaptor<
);
};

async resetToEmpty() {
async _resetToEmpty() {
fs.removeSync(this.pathToConfigDomain(this._configDomain));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export class MemoryConfigDataPersistenceAdaptor<
return MemoryConfigDataPersistenceAdaptor.data[configDomain];
}

async resetToEmpty() {
async _resetToEmpty() {
MemoryConfigDataPersistenceAdaptor.data[this._configDomain] = {};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export class RedisConfigDataPersistenceAdaptor<
super(configDomain, _configApiService);
}

async resetToEmpty() {
async _resetToEmpty() {
await (await this.getRedisInstance()).del(this.wrapWithConfigDomain());
}

Expand Down
12 changes: 6 additions & 6 deletions src/backend/users/users.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { HashService } from "backend/lib/hash/hash.service";
import { IApplicationService } from "backend/types";
import { IAccountUser, IAccountProfile } from "shared/types/user";
import { ISuccessfullAuthenticationResponse } from "shared/types/auth/portal";
import { noop } from "shared/lib/noop";
import { getPortalAuthenticationResponse } from "./portal";
import { generateAuthTokenForUsername } from "./utils";
import { usersPersistenceService } from "./shared";
Expand Down Expand Up @@ -54,10 +55,8 @@ export class UsersApiService implements IApplicationService {
async listUsers() {
const users = await this._usersPersistenceService.getAllItems();

return users.map((user) => {
const userCopy = { ...user };
delete userCopy.password;

return users.map(({ password, ...userCopy }) => {
noop(password);
return userCopy;
});
}
Expand All @@ -73,8 +72,9 @@ export class UsersApiService implements IApplicationService {
}

async getUser(username: string): Promise<IAccountProfile> {
const user = await this._usersPersistenceService.getItemOrFail(username);
delete user.password;
const { password, ...user } =
await this._usersPersistenceService.getItemOrFail(username);
noop(password);
return user;
}

Expand Down

0 comments on commit d775ccd

Please sign in to comment.