Can't get node-cache to persist data between requests - node.js

I'm writing an API endpoint in node and can't seem to get node-cache to work. I've played around with the TTL, key names and anything else I can think of. What am I missing?
const NodeCache = require( "node-cache" );
export const getLiveFeed = async (
) => {
const cache = new NodeCache({ stdTTL: 10000000, checkperiod: 120 });
const cacheKey = 'liveFeed';
let items = cache.get(cacheKey);
console.log(`Got ${items} from the cache...`);
console.log(cache.getStats());
if (Array.isArray(items)) {
console.log(`Got ${items.length} from the cache`);
return items;
}
items = [1, 2, 3, 4, 5];
cache.set(cacheKey, items);
console.log(cache.getStats());
console.log(`Setting ${items.length} items in the cache`);
return items;
};
~
Making multiple requests to the endpoint produces:
Got undefined from the cache...
{ hits: 0, misses: 1, keys: 0, ksize: 0, vsize: 0 }
{ hits: 0, misses: 1, keys: 1, ksize: 8, vsize: 200 }
Setting 5 items in the cache
Got undefined from the cache...
{ hits: 0, misses: 1, keys: 0, ksize: 0, vsize: 0 }
{ hits: 0, misses: 1, keys: 1, ksize: 8, vsize: 200 }
Setting 5 items in the cache
Got undefined from the cache...
{ hits: 0, misses: 1, keys: 0, ksize: 0, vsize: 0 }
{ hits: 0, misses: 1, keys: 1, ksize: 8, vsize: 200 }
Setting 5 items in the cache

I see now, I have to declare the cache outside of the function.
const NodeCache = require( "node-cache" );
const cache = new NodeCache({ stdTTL: 10000000, checkperiod: 120 });
export const getLiveFeed = async (
) => {
....
}

Related

Inconsistent behaviour of mocking DOMPoint in Jest

I have a number of geometry functions that use DOMPoint and DOMRect, which I want to test using jest. The framework is configured to use jsdom as test environment. Unfortunately, jsdom does not have definitions for DOMPoint and DOMRect, hence I need to mock them.
In my setupUnitTests.ts file, which is set as setupFilesAfterEnv value in jest.config.ts I have this mock call:
Object.defineProperty(globalThis, "DOMPoint", {
writable: true,
enumerable: true,
value: jest.fn().mockImplementation((x?: number, y?: number, z?: number, w?: number) => {
return {
x: x ?? 0,
y: y ?? 0,
z: z ?? 0,
w: w ?? 0,
matrixTransform: jest.fn(),
toJSON: jest.fn(),
};
}),
});
const p = new DOMPoint(1, 2, 3, 4);
The call at the end returns a DOM point instance with the expected values, fine.
In my test spec, however, the DOMPoint instance is not initialised. The mock implementation function is not called, like it is when I create a DOM point in the setup file. My spec file is very simple:
import { inflateRect, pointInRect, rectsAreEqual } from "../../../utilities/graphics";
describe("Graphics Tests", () => {
it("Rectangles", () => {
const point1 = new DOMPoint(2, 1, 3, 4);
const point2 = new DOMPoint(-95, 3, 4, 1);
const rect1 = new DOMRect(0, 0, 0, 0);
const rect2 = new DOMRect(-100, 0, 10, 10);
const rect3 = new DOMRect(0, 0, 10, 10);
const rect4 = new DOMRect(0, 0, 10, 10);
const rect5 = new DOMRect(-1, -1, 12, 12);
expect(pointInRect()).toBe(false);
expect(pointInRect(point1)).toBe(false);
expect(pointInRect(point1, rect1)).toBe(false);
expect(pointInRect(point1, rect2)).toBe(false);
expect(pointInRect(point2, rect2)).toBe(true);
expect(rectsAreEqual(rect1, rect2)).toBe(false);
expect(rectsAreEqual(rect3, rect4)).toBe(true);
expect(rectsAreEqual(rect4, rect3)).toBe(true);
expect(inflateRect(rect3, 1, 1, 1, 1)).toStrictEqual(rect5);
});
});
What's missing here? Why is the function given to jest.fn().mockImplementation not called?
The mock itself is definitely used, because when I remove it I get the error about DOMPoint not being defined.
I then moved the mock to the spec file:
describe("Graphics Tests", () => {
Object.defineProperty(global.self, "DOMPoint", {
writable: true,
enumerable: true,
value: jest.fn().mockImplementation((x?: number, y?: number, z?: number, w?: number) => {
return {
x: x ?? 0,
y: y ?? 0,
z: z ?? 0,
w: w ?? 0,
matrixTransform: jest.fn(),
toJSON: jest.fn(),
};
}),
});
it("Rectangles", () => {
const point1 = new DOMPoint(2, 1, 3, 4);
...
});
});
and found the mock function still not being called (but the mock defined). This is pretty confusing...
While debugging through the Jest code to compare the execution paths between the constructor invocations, I saw that in the spec file I had no mock config anymore (the default was used), which ultimately led me to the solution of my problem. In the jest config file I had set resetMocks: true, which caused the mocks to be removed. After setting that to false things started working as expected.

Socket.io connection refused

I'm currently working on a simple game using WebSockets (first time!). However, my console is filled with net::ERR_CONNECTION_REFUSED errors, and I can't get anything to work.
I've been trying to fix the errors for hours and have seen a few other questions online with similar problems, but nothing has worked for me so far.
Here is my code:
server.js:
const { createGameState, gameLoop } = require("./game")
const { FRAME_RATE } = require("./constants")
const io = require("socket.io")(httpServer, {
cors: {
origin: "http://localhost:3000",
methods: ["GET", "POST"]
}
});
io.on("connection", client => {
const state = createGameState()
startGameInterval(client, state)
});
function startGameInterval(client, state) {
const intervalId = setInterval(() => {
const winner = gameLoop(state);
console.log("interval");
if(!winner) {
client.emit("gameOver");
clearInterval(intervalId);
} else {
client.emit("gameover");
clearInterval(intervalId);
}
}, 1000 / FRAME_RATE); // 1000
}
io.listen(3000);
index.js (top part):
const backgroundColor = "#1c1315";
const snakeColor = "#7d7778";
const foodColor = "#f55872";
const socket = io("http://localhost:3000")
socket.on("init", handleInit());
// socket.on("gamestate", handleGameState());
const gameScreen = document.getElementById("gameScreen");
let canvas, ctx;
const gameState = {
player: {
pos: {
x: 3,
y: 10,
},
vel: {
x: 1,
y: 0,
},
snake: [
{x: 1, y: 10},
{x: 2, y: 10},
{x: 3, y: 10},
]
},
food: {
x: 7,
y: 7,
},
gridsize: 20,
};
Here is the error that I'm getting; it gets printed in the console every 5 seconds or so.
polling-xhr.js:206 GET http://localhost:3000/socket.io/?EIO=4&transport=polling&t=NW6GI07 net::ERR_CONNECTION_REFUSED
I'm very new to socket.io/websockets in general, so I don't know what this error means or what I could do to fix the issue. Any help would be massively appreciated!

Socket.io - Wrong client socket event being called on server emit

I am creating a load test application for my socket.io application. Very strange results are happening when there is an DB error on the server side. Upon DB deadlock, the server emits the correct event, but on the client side the wrong event is being called.
Server code:
(I even got rid of all DB code and just output what the DB would output so
I know it's nothing to do with the DB)
function AddUser(gObj, cb) {
if (gObj.UKEY==2)
cb({err: 901, errm: "deadlock baby"});
else if (gObj.UKEY==3)
cb(null, [3,0,0,1,0]);
else
cb(null, [1,1,0,1,0]);
}
var io=require('socket.io')(8080);
var iowm = io.of('/mpp');
iowm.on('connection', function(socket) {
console.log('in MPP connection');
socket.on('nu', function(data) {
console.log('APP: in AddUser');
AddUser(data, function(err, result) {
console.log('RC: ',data);
if (err) {
console.log(err);
iowm.emit('error', {ERRM: err.errm});
console.log('ERROR: emitted');
} else {
console.log('done: ',result);
iowm.emit('done', result);
}
});
});
});
io.httpServer.on('listening', function() {
console.log('listening on port ',io.httpServer.address().port);
});
console.log('Done...');
Client code:
(I wrap the socket events in a wrapper function (which is probably where my error is) in order to pass the right parameters to the socket events in this tight loop)
for(var i=0; i<args[4]; i++) {
age = (Math.floor(Math.random()*args[3]) + 1) * 4;
console.log('ukey: '+args[2],' age: ',age);
socket = io.connect('http://localhost:8080/mpp');
if (socket) {
var OrigSocketOn = socket.on;
socket.on = function(event, data, cb2) {
return OrigSocketOn.call(socket, event, function(res) {
console.log('ESock: ', event,' data: ',data);
switch(data.ENT) {
case 2: // connect
cb2(data);
break;
case 3: // error
cb2({data: data, result: res});
break;
default:
cb2(res);
break;
}
});
};
socket.on('connect', {ENT: 2, GKEY: args[1], UKEY: args[2], AGE: age}, function(data) {
socket.emit('nu', {GKEY: data.GKEY, UKEY: data.UKEY, AGE: data.AGE});
});
socket.on('done', {ENT: 4, UKEY: args[2], AGE: age}, function(data) {
++cnt;
console.log('SOCKET: NewUser Done cnt: ',cnt);
console.log(data);
socket.close();
if (cnt == args[4] || data[4]>0)
cb();
});
socket.on('error', {ENT: 3, GKEY: args[1], UKEY: args[2], AGE: age}, function(data) {
console.log('SOCKET: NewUser Err');
console.log(data);
if (data.result.ERRM.indexOf('deadlock') > -1) { // deadlock - try again
socket.emit('nu', {GKEY: data.GKEY, UKEY: data.UKEY, AGE: data.AGE});
} else {
socket.close();
if (++cnt == args[4])
cb();
}
});
...
Server Output:
(All looks good. UKEY 1 and 3 come back fine and it emits the 'done' event. But UKEY==2 is the deadlocked entry so it emits the 'error' event.
in MPP connection
in MPP connection
in MPP connection
APP: in AddUser
RC: { GKEY: 1, UKEY: 3, AGE: 32 }
done: [ 3, 0, 0, 1, 0 ]
APP: in AddUser
RC: { GKEY: 1, UKEY: 1, AGE: 40 }
done: [ 1, 1, 0, 1, 0 ]
APP: in AddUser
RC: { GKEY: 1, UKEY: 2, AGE: 40 }
{ err: 901, errm: 'deadlock baby' }
ERROR: emitted
Client Output: (this is the problem)
ukey: 1 age: 40
ukey: 2 age: 40
ukey: 3 age: 32
ESock: connect data: { ENT: 2, GKEY: 1, UKEY: 1, AGE: 40 }
ESock: connect data: { ENT: 2, GKEY: 1, UKEY: 2, AGE: 40 }
ESock: connect data: { ENT: 2, GKEY: 1, UKEY: 3, AGE: 32 }
ESock: done data: { ENT: 4, UKEY: 1, AGE: 40 }
SOCKET: NewUser Done cnt: 1
[ 3, 0, 0, 1, 0 ]
ESock: done data: { ENT: 4, UKEY: 2, AGE: 40 }
SOCKET: NewUser Done cnt: 2
[ 3, 0, 0, 1, 0 ]
ESock: done data: { ENT: 4, UKEY: 1, AGE: 40 }
SOCKET: NewUser Done cnt: 3
[ 1, 1, 0, 1, 0 ]
So 3 problems:
1) the client 'done' event is seemingly called 3 times, when it should only be 2 times and the 'error' event should be called once.
2) the data of the 1st and 3rd 'done' events is the same (UKEY: 1), where it should be (UKEY: 1) and (UKEY: 3)
3) (UKEY: 3) output data is not there at all.
It looks to me like on your server, where you to iowm.emit(...), you should be doing socket.emit(...).
Your client is apparently making multiple connections to the server as there's an io.connect() inside of a for(var i=0; i<args[4]; i++) loop. So, when you do iowm.emit(...) on the server, it sends to ALL the connections the client has, not just the one that the error occurred on.
1) the client 'done' event is seemingly called 3 times, when it should only be 2 times and the 'error' event should be called once.
Because you're broadcasting the error to all client connections, not just to the one socket that the error occured on.

vue mutation push object reference?

addSentence: (state) => {
const obj = state;
// next line is correct;
obj.sentences.push({ ...obj.current });
// change to next line, get error
// obj.sentences.push(obj.current);
obj.current = new Sentence();
},
import Constants from './Constants';
export default class Sentence {
constructor(config) {
this.text = '';
this.fontFamily = 'KaiTi';
this.fontSize = 16;
this.fontStyle = '';
this.appearStyle = {
name: 'type',
speed: 40,
startDelay: 0,
};
this.disappearStyle = {
name: 'backspace',
speed: 80,
startDelay: 0,
smartBackspace: true,
};
}
play(context) {
}
drawText() {
}
}
state.cuurent is an object of type Sentence.
And state.sentences = [Sentence]
This is a mutation handler.
Error:
[vuex] Do not mutate vuex store state outside mutation handlers.

Not able to Display Data properly in node cli-table

I'm trying to display data that i received from an api on console using cli-table. The api call and everything works fine. I'm just having trouble displaying the output. Here's my code
const
url = require('./url'),
Table = require('cli-table2'),
fs = require('fs'),
inquirer = require('inquirer')
let table = new Table({
head: ['Name', 'Type', 'Language',
'Genres', 'Status', 'Premiered', 'OfficialSite', 'Schedule', 'Rating', 'Streamed On', 'Externals', 'Images', 'summary'
],
colWidths: [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]
});
const search = (item) => {
let shows = []
url.wordsearch(item)
.then(result => {
//console.log(result)
result.forEach(element => {
shows.push({ 'name': element.show['name'], 'value': element.show['id'] })
})
//console.log(shows)
inquirer.prompt([{
type: 'checkbox',
message: 'select tvshows you want see',
name: 'tvshow',
pageSize: 25,
choices: shows,
validate: (answer) => {
if (answer.length < 1) {
return "You must choose at least one card";
}
return true;
}
}]).then((answer) => {
//console.log(answer)
printresult(answer)
})
})
.catch(err => console.log(err))
}
const printresult = (answer) => {
answer.tvshow.forEach(show => {
url.idsearch(show)
.then(element => {
clean(element)
table.push([element['name'],
element['type'],
element['language'],
element['genres'],
element['status'],
element['premiered'],
element['officialSite'],
`Time :${element['schedule']['time']} \n Days: ${element['schedule']['days']}`,
element['rating'],
` name:${element['network']['name']}\n Country: ${element['network']['country']}`,
`tvrage:${element['externals']['tvrage']}\n thetvdb:${element['externals']['thetvdb']}\n imdb:${element['externals']['imdb']}`,
`medium:${element['image']['medium']}\n original:${element['image']['original']}`,
element['summary']
])
console.log(table.toString())
})
})
}
What am I doing wrong ? I want the output in a proper table format with no ... or anything. The printresult method does the work of printing to the console. I'm attaching a screenshot of my output.

Resources