Skip to content
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
24 changes: 7 additions & 17 deletions src/helpers/cache/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,13 @@ export default class Cache {
}

async startScheduledUpdates(options = {}) {
this.#workerManager = new CacheWorkerManager(options);

this.#workerManager.setOnCacheUpdates((updates) =>
this.#handleCacheUpdates(updates));

this.#workerManager.setOnCacheDeletions((deletions) =>
this.#handleCacheDeletions(deletions));

this.#workerManager.setOnCacheVersionRequest((domainId) =>
this.#handleCacheVersionRequest(domainId));

this.#workerManager.setOnCachedDomainIdsRequest(() =>
this.#handleCachedDomainIdsRequest());

this.#workerManager.setOnError((error) => {
Logger.error('Cache worker error:', error);
});
this.#workerManager = new CacheWorkerManager({
onCacheUpdates: (updates) => this.#handleCacheUpdates(updates),
onCacheDeletions: (deletions) => this.#handleCacheDeletions(deletions),
onCacheVersionRequest: (domainId) => this.#handleCacheVersionRequest(domainId),
onCachedDomainIdsRequest: () => this.#handleCachedDomainIdsRequest(),
onError: (error) => Logger.error('Cache worker error:', error)
}, options);

await this.#workerManager.start();
}
Expand Down
73 changes: 16 additions & 57 deletions src/helpers/cache/worker-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@ export const STATUS_TYPE = {
export class CacheWorkerManager {
DEFAULT_INTERVAL = 5000;

constructor(options = {}) {
constructor(eventHandlers, options) {
this.worker = null;
this.status = STATUS_TYPE.STOPPED;
this.onCacheUpdates = null;
this.onCacheDeletions = null;
this.onCachedDomainIdsRequest = null;
this.onError = null;
this.onCacheUpdates = eventHandlers.onCacheUpdates;
this.onCacheDeletions = eventHandlers.onCacheDeletions;
this.onCachedDomainIdsRequest = eventHandlers.onCachedDomainIdsRequest;
this.onCacheVersionRequest = eventHandlers.onCacheVersionRequest;
this.onError = eventHandlers.onError;

this.options = {
interval: this.DEFAULT_INTERVAL,
...options
Expand All @@ -56,35 +58,25 @@ export class CacheWorkerManager {
this.status = STATUS_TYPE.STOPPED;
}],
[EVENT_TYPE.CACHE_UPDATES, (message) => {
if (this.onCacheUpdates) {
this.onCacheUpdates(message.updates);
}
this.onCacheUpdates(message.updates);
}],
[EVENT_TYPE.CACHE_DELETIONS, (message) => {
if (this.onCacheDeletions) {
this.onCacheDeletions(message.deletions);
}
this.onCacheDeletions(message.deletions);
}],
[EVENT_TYPE.REQUEST_CACHE_VERSION, (message) => {
if (this.onCacheVersionRequest) {
this.onCacheVersionRequest(message.domainId);
}
this.onCacheVersionRequest(message.domainId);
}],
[EVENT_TYPE.REQUEST_CACHED_DOMAIN_IDS, () => {
if (this.onCachedDomainIdsRequest) {
this.onCachedDomainIdsRequest();
}
this.onCachedDomainIdsRequest();
}],
[EVENT_TYPE.ERROR, (message) => {
if (this.onError) {
this.onError(new Error(message.error));
}
this.onError(new Error(message.error));
}]
]);
}

start() {
return new Promise((resolve, reject) => {
return new Promise((resolve) => {
const workerPath = join(__dirname, 'worker.js');
const eventHandlers = this.#buildEvents(resolve);

Expand All @@ -93,20 +85,9 @@ export class CacheWorkerManager {
});

this.worker.on('message', (message) => {
const handler = eventHandlers.get(message.type);
if (handler) {
handler(message);
}
});

this.worker.on('error', (error) => {
this.status = STATUS_TYPE.ERROR;
if (this.onError) {
this.onError(error);
}
reject(error);
eventHandlers.get(message.type)(message);
});

this.worker.on('exit', (code) => {
const wasTerminating = this.status === STATUS_TYPE.STOPPING;
this.status = STATUS_TYPE.STOPPED;
Expand All @@ -124,15 +105,13 @@ export class CacheWorkerManager {
}

stop() {
this.status = STATUS_TYPE.STOPPING;

return new Promise((resolve) => {
const cleanup = () => {
if (this.worker) {
this.worker.terminate();
this.worker = null;
}
this.status = STATUS_TYPE.STOPPED;
this.status = STATUS_TYPE.STOPPING;
resolve();
};

Expand All @@ -156,22 +135,6 @@ export class CacheWorkerManager {
return this.status;
}

setOnCacheUpdates(callback) {
this.onCacheUpdates = callback;
}

setOnCacheDeletions(callback) {
this.onCacheDeletions = callback;
}

setOnCacheVersionRequest(callback) {
this.onCacheVersionRequest = callback;
}

setOnCachedDomainIdsRequest(callback) {
this.onCachedDomainIdsRequest = callback;
}

sendCacheVersionResponse(domainId, cachedVersion) {
if (this.worker && this.status === STATUS_TYPE.RUNNING) {
this.worker.postMessage({
Expand All @@ -190,8 +153,4 @@ export class CacheWorkerManager {
});
}
}

setOnError(callback) {
this.onError = callback;
}
}
16 changes: 6 additions & 10 deletions src/helpers/cache/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ async function refreshCache() {
isRunning = true;

try {
const domains = await getAllDomains();
const domains = await getAllDomains('lastUpdate');
const deletions = await checkForDeletions(domains);
const updates = await checkForDomainUpdates(domains);

Expand Down Expand Up @@ -81,17 +81,13 @@ async function refreshCache() {
async function checkForDeletions(domains) {
const deletions = [];

try {
const currentDomainIds = new Set(domains.map(domain => domain._id.toString()));
const cachedDomainIds = await getAllCachedDomainIds();
const currentDomainIds = new Set(domains.map(domain => domain._id.toString()));
const cachedDomainIds = await getAllCachedDomainIds();

for (const cachedDomainId of cachedDomainIds) {
if (!currentDomainIds.has(cachedDomainId)) {
deletions.push(cachedDomainId);
}
for (const cachedDomainId of cachedDomainIds) {
if (!currentDomainIds.has(cachedDomainId)) {
deletions.push(cachedDomainId);
}
} catch (error) {
Logger.error('Error checking for deletions:', error);
}

return deletions;
Expand Down
4 changes: 2 additions & 2 deletions src/services/domain.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ export async function getDomainById(id) {
return Domain.findById(id).exec();
}

export async function getAllDomains() {
return Domain.find().exec();
export async function getAllDomains(select) {
return Domain.find().select(select).exec();
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import mongoose from 'mongoose';
import '../../src/db/mongoose';
import '../../../src/db/mongoose';

import { domainId, setupDatabase } from '../fixtures/db_api';
import Domain from '../../src/models/domain';
import Cache from '../../src/helpers/cache';
import { domainId, setupDatabase } from '../../fixtures/db_api';
import Domain from '../../../src/models/domain';
import Cache from '../../../src/helpers/cache';

let cache;

Expand All @@ -24,7 +24,7 @@ describe('Test cache', () => {
await cache.stopScheduledUpdates();
});

test('UNIT_SUITE - Should initialize cache', async () => {
test('CACHE_SUITE - Should initialize cache', async () => {
// test
cache = Cache.getInstance();
await cache.initializeCache();
Expand All @@ -37,7 +37,7 @@ describe('Test cache', () => {
expect(cacheSingle).toBeDefined();
});

test('UNIT_SUITE - Should initialize schduled cache update', async () => {
test('CACHE_SUITE - Should initialize schduled cache update', async () => {
// test
cache = Cache.getInstance();
await cache.initializeCache();
Expand All @@ -47,7 +47,7 @@ describe('Test cache', () => {
expect(cache.status()).toBe('running');
});

test('UNIT_SUITE - Should update cache when new Domain version is available', async () => {
test('CACHE_SUITE - Should update cache when new Domain version is available', async () => {
// test
cache = Cache.getInstance();
await cache.initializeCache();
Expand All @@ -65,7 +65,7 @@ describe('Test cache', () => {
expect(updatedSuccessfully).toBe(true);
}, 20000);

test('UNIT_SUITE - Should update cache when new Domain is created', async () => {
test('CACHE_SUITE - Should update cache when new Domain is created', async () => {
// test
cache = Cache.getInstance();
await cache.initializeCache();
Expand All @@ -83,7 +83,7 @@ describe('Test cache', () => {
expect(updatedSuccessfully).toBe(true);
}, 20000);

test('UNIT_SUITE - Should update cache when Domain is deleted', async () => {
test('CACHE_SUITE - Should update cache when Domain is deleted', async () => {
// test
cache = Cache.getInstance();
await cache.initializeCache();
Expand Down
55 changes: 55 additions & 0 deletions tests/unit-test/cache/worker-manager.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { CacheWorkerManager } from '../../../src/helpers/cache/worker-manager';

describe('Test worker manager', () => {

test('CACHE_SUITE - Should start/stop worker manager', async () => {
const workerManager = new CacheWorkerManager({
onCacheUpdates: () => {},
onCacheDeletions: () => {},
onCacheVersionRequest: () => {},
onCachedDomainIdsRequest: () => {},
onError: () => {}
}, { interval: 500 });

// Start the worker manager
await workerManager.start();
await new Promise(resolve => setTimeout(resolve, 500));

let status = workerManager.getStatus();
expect(status).toBeDefined();
expect(status).toBe('running');

// Stop the worker manager
await workerManager.stop();
await new Promise(resolve => setTimeout(resolve, 500));

status = workerManager.getStatus();
expect(status).toBeDefined();
expect(status).toBe('stopped');
});

test('CACHE_SUITE - Should handle error when cache response is invalid', async () => {
let error = false;
const workerManager = new CacheWorkerManager({
onCacheUpdates: () => {},
onCacheDeletions: () => {},
onCacheVersionRequest: () => {},
onCachedDomainIdsRequest: () => badCacheResponse(workerManager),
onError: () => {
error = true;
}
}, { interval: 500 });

// Start the worker manager
await workerManager.start();
await new Promise(resolve => setTimeout(resolve, 1000));

// Stop the worker manager
await workerManager.stop();
expect(error).toBe(true);
});
});

function badCacheResponse(workerManager) {
workerManager.sendCachedDomainIdsResponse(null);
}