clear lot cache messaging
parent
e7b4753123
commit
18f5dc7103
|
|
@ -25,7 +25,6 @@ for (let index = 0; index < processCount; index += 1) {
|
||||||
activeWorkers.set(worker.process.pid, worker);
|
activeWorkers.set(worker.process.pid, worker);
|
||||||
}
|
}
|
||||||
cluster.on('message', (worker, message) => {
|
cluster.on('message', (worker, message) => {
|
||||||
if (message?.messageType === 'clearCache') {
|
|
||||||
for (const [pid, worker] of activeWorkers.entries()) {
|
for (const [pid, worker] of activeWorkers.entries()) {
|
||||||
if (worker === undefined || pid === message.pid) {
|
if (worker === undefined || pid === message.pid) {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -33,7 +32,6 @@ cluster.on('message', (worker, message) => {
|
||||||
debug('Relaying message to workers');
|
debug('Relaying message to workers');
|
||||||
worker.send(message);
|
worker.send(message);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
cluster.on('exit', (worker, code, signal) => {
|
cluster.on('exit', (worker, code, signal) => {
|
||||||
debug(`Worker ${worker.process.pid.toString()} has been killed`);
|
debug(`Worker ${worker.process.pid.toString()} has been killed`);
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,6 @@ for (let index = 0; index < processCount; index += 1) {
|
||||||
}
|
}
|
||||||
|
|
||||||
cluster.on('message', (worker, message: WorkerMessage) => {
|
cluster.on('message', (worker, message: WorkerMessage) => {
|
||||||
if (message?.messageType === 'clearCache') {
|
|
||||||
for (const [pid, worker] of activeWorkers.entries()) {
|
for (const [pid, worker] of activeWorkers.entries()) {
|
||||||
if (worker === undefined || pid === message.pid) {
|
if (worker === undefined || pid === message.pid) {
|
||||||
continue
|
continue
|
||||||
|
|
@ -54,7 +53,6 @@ cluster.on('message', (worker, message: WorkerMessage) => {
|
||||||
debug('Relaying message to workers')
|
debug('Relaying message to workers')
|
||||||
worker.send(message)
|
worker.send(message)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
cluster.on('exit', (worker, code, signal) => {
|
cluster.on('exit', (worker, code, signal) => {
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ import { getWorkOrderTypes as getWorkOrderTypesFromDatabase } from './lotOccupan
|
||||||
import { getWorkOrderMilestoneTypes as getWorkOrderMilestoneTypesFromDatabase } from './lotOccupancyDB/getWorkOrderMilestoneTypes.js'
|
import { getWorkOrderMilestoneTypes as getWorkOrderMilestoneTypesFromDatabase } from './lotOccupancyDB/getWorkOrderMilestoneTypes.js'
|
||||||
|
|
||||||
import type * as recordTypes from '../types/recordTypes'
|
import type * as recordTypes from '../types/recordTypes'
|
||||||
import type { WorkerMessage } from '../types/applicationTypes'
|
import type { ClearCacheWorkerMessage } from '../types/applicationTypes'
|
||||||
|
|
||||||
import Debug from 'debug'
|
import Debug from 'debug'
|
||||||
const debug = Debug(`lot-occupancy-system:functions.cache:${process.pid}`)
|
const debug = Debug(`lot-occupancy-system:functions.cache:${process.pid}`)
|
||||||
|
|
@ -343,7 +343,7 @@ export function clearCacheByTableName(
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (relayMessage && cluster.isWorker) {
|
if (relayMessage && cluster.isWorker) {
|
||||||
const workerMessage: WorkerMessage = {
|
const workerMessage: ClearCacheWorkerMessage = {
|
||||||
messageType: 'clearCache',
|
messageType: 'clearCache',
|
||||||
tableName,
|
tableName,
|
||||||
timeMillis: Date.now(),
|
timeMillis: Date.now(),
|
||||||
|
|
@ -357,7 +357,7 @@ export function clearCacheByTableName(
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
|
|
||||||
process.on('message', (message: WorkerMessage) => {
|
process.on('message', (message: ClearCacheWorkerMessage) => {
|
||||||
if (message.messageType === 'clearCache' && message.pid !== process.pid) {
|
if (message.messageType === 'clearCache' && message.pid !== process.pid) {
|
||||||
debug(`Clearing cache: ${message.tableName}`)
|
debug(`Clearing cache: ${message.tableName}`)
|
||||||
clearCacheByTableName(message.tableName, false)
|
clearCacheByTableName(message.tableName, false)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
export declare function getNextLotId(lotId: number): Promise<number | undefined>;
|
export declare function getNextLotId(lotId: number): Promise<number | undefined>;
|
||||||
export declare function getPreviousLotId(lotId: number): Promise<number | undefined>;
|
export declare function getPreviousLotId(lotId: number): Promise<number | undefined>;
|
||||||
export declare function clearNextPreviousLotIdCache(lotId?: number): void;
|
export declare function clearNextPreviousLotIdCache(lotId: number | -1, relayMessage?: boolean): void;
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,32 @@
|
||||||
|
import cluster from 'node:cluster';
|
||||||
import NodeCache from 'node-cache';
|
import NodeCache from 'node-cache';
|
||||||
import getPreviousLotIdFromDatabase from './lotOccupancyDB/getPreviousLotId.js';
|
import getPreviousLotIdFromDatabase from './lotOccupancyDB/getPreviousLotId.js';
|
||||||
import getNextLotIdFromDatabase from './lotOccupancyDB/getNextLotId.js';
|
import getNextLotIdFromDatabase from './lotOccupancyDB/getNextLotId.js';
|
||||||
|
import Debug from 'debug';
|
||||||
|
const debug = Debug(`lot-occupancy-system:functions.lots:${process.pid}`);
|
||||||
const cacheOptions = {
|
const cacheOptions = {
|
||||||
stdTTL: 2 * 60,
|
stdTTL: 2 * 60,
|
||||||
useClones: false
|
useClones: false
|
||||||
};
|
};
|
||||||
const previousLotIdCache = new NodeCache(cacheOptions);
|
const previousLotIdCache = new NodeCache(cacheOptions);
|
||||||
const nextLotIdCache = new NodeCache(cacheOptions);
|
const nextLotIdCache = new NodeCache(cacheOptions);
|
||||||
function cacheLotIds(lotId, nextLotId) {
|
function cacheLotIds(lotId, nextLotId, relayMessage = true) {
|
||||||
previousLotIdCache.set(nextLotId, lotId);
|
previousLotIdCache.set(nextLotId, lotId);
|
||||||
nextLotIdCache.set(lotId, nextLotId);
|
nextLotIdCache.set(lotId, nextLotId);
|
||||||
|
try {
|
||||||
|
if (relayMessage && cluster.isWorker) {
|
||||||
|
const workerMessage = {
|
||||||
|
messageType: 'cacheLotIds',
|
||||||
|
lotId,
|
||||||
|
nextLotId,
|
||||||
|
timeMillis: Date.now(),
|
||||||
|
pid: process.pid
|
||||||
|
};
|
||||||
|
debug(`Sending cache lot ids from worker: (${lotId}, ${nextLotId})`);
|
||||||
|
process.send(workerMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
}
|
}
|
||||||
export async function getNextLotId(lotId) {
|
export async function getNextLotId(lotId) {
|
||||||
let nextLotId = nextLotIdCache.get(lotId);
|
let nextLotId = nextLotIdCache.get(lotId);
|
||||||
|
|
@ -31,8 +48,8 @@ export async function getPreviousLotId(lotId) {
|
||||||
}
|
}
|
||||||
return previousLotId;
|
return previousLotId;
|
||||||
}
|
}
|
||||||
export function clearNextPreviousLotIdCache(lotId) {
|
export function clearNextPreviousLotIdCache(lotId, relayMessage = true) {
|
||||||
if (lotId === undefined) {
|
if (lotId === undefined || lotId === -1) {
|
||||||
previousLotIdCache.flushAll();
|
previousLotIdCache.flushAll();
|
||||||
nextLotIdCache.flushAll();
|
nextLotIdCache.flushAll();
|
||||||
return;
|
return;
|
||||||
|
|
@ -47,4 +64,33 @@ export function clearNextPreviousLotIdCache(lotId) {
|
||||||
previousLotIdCache.del(nextLotId);
|
previousLotIdCache.del(nextLotId);
|
||||||
nextLotIdCache.del(lotId);
|
nextLotIdCache.del(lotId);
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
if (relayMessage && cluster.isWorker) {
|
||||||
|
const workerMessage = {
|
||||||
|
messageType: 'clearNextPreviousLotIdCache',
|
||||||
|
lotId,
|
||||||
|
timeMillis: Date.now(),
|
||||||
|
pid: process.pid
|
||||||
|
};
|
||||||
|
debug(`Sending clear next/previous lot cache from worker: ${lotId}`);
|
||||||
|
process.send(workerMessage);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
process.on('message', (message) => {
|
||||||
|
if (message.pid !== process.pid) {
|
||||||
|
switch (message.messageType) {
|
||||||
|
case 'cacheLotIds': {
|
||||||
|
debug(`Caching lot ids: (${message.lotId}, ${message.nextLotId})`);
|
||||||
|
cacheLotIds(message.lotId, message.nextLotId, false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'clearNextPreviousLotIdCache': {
|
||||||
|
debug(`Clearing next/previous lot cache: ${message.lotId}`);
|
||||||
|
clearNextPreviousLotIdCache(message.lotId, false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,18 @@
|
||||||
|
import cluster from 'node:cluster'
|
||||||
|
|
||||||
import NodeCache from 'node-cache'
|
import NodeCache from 'node-cache'
|
||||||
|
|
||||||
import getPreviousLotIdFromDatabase from './lotOccupancyDB/getPreviousLotId.js'
|
import getPreviousLotIdFromDatabase from './lotOccupancyDB/getPreviousLotId.js'
|
||||||
import getNextLotIdFromDatabase from './lotOccupancyDB/getNextLotId.js'
|
import getNextLotIdFromDatabase from './lotOccupancyDB/getNextLotId.js'
|
||||||
|
|
||||||
|
import type {
|
||||||
|
CacheLotIdsWorkerMessage,
|
||||||
|
ClearNextPreviousLotIdsCacheWorkerMessage
|
||||||
|
} from '../types/applicationTypes.js'
|
||||||
|
|
||||||
|
import Debug from 'debug'
|
||||||
|
const debug = Debug(`lot-occupancy-system:functions.lots:${process.pid}`)
|
||||||
|
|
||||||
const cacheOptions: NodeCache.Options = {
|
const cacheOptions: NodeCache.Options = {
|
||||||
stdTTL: 2 * 60, // two minutes
|
stdTTL: 2 * 60, // two minutes
|
||||||
useClones: false
|
useClones: false
|
||||||
|
|
@ -12,9 +22,29 @@ const previousLotIdCache = new NodeCache(cacheOptions)
|
||||||
|
|
||||||
const nextLotIdCache = new NodeCache(cacheOptions)
|
const nextLotIdCache = new NodeCache(cacheOptions)
|
||||||
|
|
||||||
function cacheLotIds(lotId: number, nextLotId: number): void {
|
function cacheLotIds(
|
||||||
|
lotId: number,
|
||||||
|
nextLotId: number,
|
||||||
|
relayMessage = true
|
||||||
|
): void {
|
||||||
previousLotIdCache.set(nextLotId, lotId)
|
previousLotIdCache.set(nextLotId, lotId)
|
||||||
nextLotIdCache.set(lotId, nextLotId)
|
nextLotIdCache.set(lotId, nextLotId)
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (relayMessage && cluster.isWorker) {
|
||||||
|
const workerMessage: CacheLotIdsWorkerMessage = {
|
||||||
|
messageType: 'cacheLotIds',
|
||||||
|
lotId,
|
||||||
|
nextLotId,
|
||||||
|
timeMillis: Date.now(),
|
||||||
|
pid: process.pid
|
||||||
|
}
|
||||||
|
|
||||||
|
debug(`Sending cache lot ids from worker: (${lotId}, ${nextLotId})`)
|
||||||
|
|
||||||
|
process.send!(workerMessage)
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getNextLotId(lotId: number): Promise<number | undefined> {
|
export async function getNextLotId(lotId: number): Promise<number | undefined> {
|
||||||
|
|
@ -47,8 +77,11 @@ export async function getPreviousLotId(
|
||||||
return previousLotId
|
return previousLotId
|
||||||
}
|
}
|
||||||
|
|
||||||
export function clearNextPreviousLotIdCache(lotId?: number): void {
|
export function clearNextPreviousLotIdCache(
|
||||||
if (lotId === undefined) {
|
lotId: number | -1,
|
||||||
|
relayMessage = true
|
||||||
|
): void {
|
||||||
|
if (lotId === undefined || lotId === -1) {
|
||||||
previousLotIdCache.flushAll()
|
previousLotIdCache.flushAll()
|
||||||
nextLotIdCache.flushAll()
|
nextLotIdCache.flushAll()
|
||||||
return
|
return
|
||||||
|
|
@ -67,4 +100,43 @@ export function clearNextPreviousLotIdCache(lotId?: number): void {
|
||||||
previousLotIdCache.del(nextLotId)
|
previousLotIdCache.del(nextLotId)
|
||||||
nextLotIdCache.del(lotId)
|
nextLotIdCache.del(lotId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (relayMessage && cluster.isWorker) {
|
||||||
|
const workerMessage: ClearNextPreviousLotIdsCacheWorkerMessage = {
|
||||||
|
messageType: 'clearNextPreviousLotIdCache',
|
||||||
|
lotId,
|
||||||
|
timeMillis: Date.now(),
|
||||||
|
pid: process.pid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug(`Sending clear next/previous lot cache from worker: ${lotId}`)
|
||||||
|
|
||||||
|
process.send!(workerMessage)
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
|
||||||
|
process.on(
|
||||||
|
'message',
|
||||||
|
(
|
||||||
|
message:
|
||||||
|
| ClearNextPreviousLotIdsCacheWorkerMessage
|
||||||
|
| CacheLotIdsWorkerMessage
|
||||||
|
) => {
|
||||||
|
if (message.pid !== process.pid) {
|
||||||
|
switch (message.messageType) {
|
||||||
|
case 'cacheLotIds': {
|
||||||
|
debug(`Caching lot ids: (${message.lotId}, ${message.nextLotId})`)
|
||||||
|
cacheLotIds(message.lotId, message.nextLotId, false)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'clearNextPreviousLotIdCache': {
|
||||||
|
debug(`Clearing next/previous lot cache: ${message.lotId}`)
|
||||||
|
clearNextPreviousLotIdCache(message.lotId, false)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { acquireConnection } from './pool.js';
|
import { acquireConnection } from './pool.js';
|
||||||
import { addOrUpdateLotField } from './addOrUpdateLotField.js';
|
import { addOrUpdateLotField } from './addOrUpdateLotField.js';
|
||||||
import { deleteLotField } from './deleteLotField.js';
|
import { deleteLotField } from './deleteLotField.js';
|
||||||
|
import { clearNextPreviousLotIdCache } from '../functions.lots.js';
|
||||||
export async function updateLot(lotForm, requestSession) {
|
export async function updateLot(lotForm, requestSession) {
|
||||||
const database = await acquireConnection();
|
const database = await acquireConnection();
|
||||||
const rightNowMillis = Date.now();
|
const rightNowMillis = Date.now();
|
||||||
|
|
@ -32,6 +33,9 @@ export async function updateLot(lotForm, requestSession) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
database.release();
|
database.release();
|
||||||
|
clearNextPreviousLotIdCache(typeof lotForm.lotId === 'number'
|
||||||
|
? lotForm.lotId
|
||||||
|
: Number.parseInt(lotForm.lotId, 10));
|
||||||
return result.changes > 0;
|
return result.changes > 0;
|
||||||
}
|
}
|
||||||
export async function updateLotStatus(lotId, lotStatusId, requestSession) {
|
export async function updateLotStatus(lotId, lotStatusId, requestSession) {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import { addOrUpdateLotField } from './addOrUpdateLotField.js'
|
||||||
import { deleteLotField } from './deleteLotField.js'
|
import { deleteLotField } from './deleteLotField.js'
|
||||||
|
|
||||||
import type * as recordTypes from '../../types/recordTypes'
|
import type * as recordTypes from '../../types/recordTypes'
|
||||||
|
import { clearNextPreviousLotIdCache } from '../functions.lots.js'
|
||||||
|
|
||||||
interface UpdateLotForm {
|
interface UpdateLotForm {
|
||||||
lotId: string | number
|
lotId: string | number
|
||||||
|
|
@ -87,6 +88,12 @@ export async function updateLot(
|
||||||
|
|
||||||
database.release()
|
database.release()
|
||||||
|
|
||||||
|
clearNextPreviousLotIdCache(
|
||||||
|
typeof lotForm.lotId === 'number'
|
||||||
|
? lotForm.lotId
|
||||||
|
: Number.parseInt(lotForm.lotId, 10)
|
||||||
|
)
|
||||||
|
|
||||||
return result.changes > 0
|
return result.changes > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "cross-env NODE_ENV=production node ./bin/www.js",
|
"start": "cross-env NODE_ENV=production node ./bin/www.js",
|
||||||
"dev:test": "cross-env NODE_ENV=dev DEBUG=lot-occupancy-system:*,dynamics-gp:* TEST_DATABASES=true nodemon --inspect ./bin/www.js",
|
"dev:test": "cross-env NODE_ENV=dev DEBUG=lot-occupancy-system:*,dynamics-gp:* TEST_DATABASES=true nodemon --inspect ./bin/www.js",
|
||||||
"dev:test:process": "cross-env NODE_ENV=dev DEBUG=lot-occupancy-system:* TEST_DATABASES=true nodemon ./bin/wwwProcess.js",
|
"dev:test:process": "cross-env NODE_ENV=dev DEBUG=lot-occupancy-system:* TEST_DATABASES=true nodemon --inspect ./bin/wwwProcess.js",
|
||||||
"dev:live": "cross-env NODE_ENV=dev DEBUG=lot-occupancy-system:* nodemon ./bin/www.js",
|
"dev:live": "cross-env NODE_ENV=dev DEBUG=lot-occupancy-system:* nodemon --inspect ./bin/www.js",
|
||||||
"cy:open": "cypress open --config-file cypress.config.js",
|
"cy:open": "cypress open --config-file cypress.config.js",
|
||||||
"cy:run": "cypress run --config-file cypress.config.js",
|
"cy:run": "cypress run --config-file cypress.config.js",
|
||||||
"cy:run:firefox": "cypress run --config-file cypress.config.js --browser firefox",
|
"cy:run:firefox": "cypress run --config-file cypress.config.js --browser firefox",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,18 @@
|
||||||
export interface WorkerMessage {
|
export interface WorkerMessage {
|
||||||
messageType: 'clearCache';
|
messageType: string;
|
||||||
tableName: string;
|
|
||||||
timeMillis: number;
|
timeMillis: number;
|
||||||
pid: number;
|
pid: number;
|
||||||
}
|
}
|
||||||
|
export interface ClearCacheWorkerMessage extends WorkerMessage {
|
||||||
|
messageType: 'clearCache';
|
||||||
|
tableName: string;
|
||||||
|
}
|
||||||
|
export interface CacheLotIdsWorkerMessage extends WorkerMessage {
|
||||||
|
messageType: 'cacheLotIds';
|
||||||
|
lotId: number;
|
||||||
|
nextLotId: number;
|
||||||
|
}
|
||||||
|
export interface ClearNextPreviousLotIdsCacheWorkerMessage extends WorkerMessage {
|
||||||
|
messageType: 'clearNextPreviousLotIdCache';
|
||||||
|
lotId: number;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,22 @@
|
||||||
export interface WorkerMessage {
|
export interface WorkerMessage {
|
||||||
messageType: 'clearCache'
|
messageType: string
|
||||||
tableName: string
|
|
||||||
timeMillis: number
|
timeMillis: number
|
||||||
pid: number
|
pid: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ClearCacheWorkerMessage extends WorkerMessage {
|
||||||
|
messageType: 'clearCache'
|
||||||
|
tableName: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CacheLotIdsWorkerMessage extends WorkerMessage {
|
||||||
|
messageType: 'cacheLotIds'
|
||||||
|
lotId: number
|
||||||
|
nextLotId: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ClearNextPreviousLotIdsCacheWorkerMessage
|
||||||
|
extends WorkerMessage {
|
||||||
|
messageType: 'clearNextPreviousLotIdCache'
|
||||||
|
lotId: number
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue