diff --git a/src/helpers/cache/index.js b/src/helpers/cache/index.js index 7880da6..fae71a7 100644 --- a/src/helpers/cache/index.js +++ b/src/helpers/cache/index.js @@ -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(); } diff --git a/src/helpers/cache/worker-manager.js b/src/helpers/cache/worker-manager.js index 7bd3dcb..fd65889 100644 --- a/src/helpers/cache/worker-manager.js +++ b/src/helpers/cache/worker-manager.js @@ -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 @@ -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); @@ -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; @@ -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(); }; @@ -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({ @@ -190,8 +153,4 @@ export class CacheWorkerManager { }); } } - - setOnError(callback) { - this.onError = callback; - } } diff --git a/src/helpers/cache/worker.js b/src/helpers/cache/worker.js index f0f2c0f..8788cfc 100644 --- a/src/helpers/cache/worker.js +++ b/src/helpers/cache/worker.js @@ -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); @@ -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; diff --git a/src/services/domain.js b/src/services/domain.js index 7f97202..4b3103f 100644 --- a/src/services/domain.js +++ b/src/services/domain.js @@ -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(); } \ No newline at end of file diff --git a/tests/unit-test/cache.test.js b/tests/unit-test/cache/cache.test.js similarity index 86% rename from tests/unit-test/cache.test.js rename to tests/unit-test/cache/cache.test.js index 9d937c4..dab4ce3 100644 --- a/tests/unit-test/cache.test.js +++ b/tests/unit-test/cache/cache.test.js @@ -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; @@ -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(); @@ -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(); @@ -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(); @@ -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(); @@ -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(); diff --git a/tests/unit-test/cache/worker-manager.test.js b/tests/unit-test/cache/worker-manager.test.js new file mode 100644 index 0000000..b7ee33e --- /dev/null +++ b/tests/unit-test/cache/worker-manager.test.js @@ -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); +} \ No newline at end of file