Skip to content

Commit

Permalink
bumped minor version
Browse files Browse the repository at this point in the history
  • Loading branch information
pubalokta committed Nov 11, 2024
1 parent 1ffff4d commit b14048c
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 44 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ on:

jobs:
test:
env:
CI: true
timeout-minutes: 10
runs-on: ubuntu-latest
strategy:
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "limitd-redis",
"version": "8.3.1",
"version": "8.4.0",
"description": "A database client for limits on top of redis",
"main": "index.js",
"repository": {
Expand Down Expand Up @@ -30,6 +30,7 @@
"mockdate": "^3.0.5",
"nyc": "^14.1.1",
"sinon": "^19.0.2",
"sockopt": "^2.0.1",
"toxiproxy-node-client": "^2.0.6"
}
}
68 changes: 25 additions & 43 deletions test/db.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const assert = require('chai').assert;
const { endOfMonthTimestamp, replicateHashtag } = require('../lib/utils');
const sinon = require('sinon');
const { exec } = require('child_process');
const { getSockOptValue } = require('./testutils');

const buckets = {
ip: {
Expand Down Expand Up @@ -145,48 +146,28 @@ module.exports.tests = (clientCreator, opts) => {
});

describe('KeepAlive', () => {
const checkSocketOption = (portPairs, option, expectedValue, delta, done) => {
const pid = process.pid;
const command = `lsof -a -p ${pid} -i 4 -T f`;

exec(command, (error, stdout, stderr) => {
if (error) {
return done(error);
}
if (stderr) {
return done(new Error(stderr));
}

const keepAliveOption = stdout
.split('\n')
.find(line =>
portPairs.some(portPair =>
line.includes(`:${portPair.localPort}`)
&& line.includes(`:${portPair.remotePort}`)
)
);
assert.isNotNull(keepAliveOption, `no entry found for port ${portPairs}: ${stdout}`);
assert.notEqual(keepAliveOption, undefined, `no entry found for port ${portPairs}: ${stdout}`);
assert.include(keepAliveOption, option, `${option} option not found: ${keepAliveOption}`);

const keepAliveValue = parseInt(keepAliveOption.match(new RegExp(`${option}=(\\d+)`))[1], 10);
assert.isAtLeast(keepAliveValue, expectedValue - delta, `${option} is lesser than expected`);
assert.isAtMost(keepAliveValue, expectedValue + delta, `${option} is greater than expected`);

done();
});
const assertSockOpt = (expected, delta, done) => (err, value) => {
if (err) {
done(err);
}
assert.isAtLeast(value, expected - delta, 'SO=KEEPALIVE is lesser than expected');
assert.isAtMost(value, expected + delta, 'SO=KEEPALIVE is greater than expected');
done();
};


it('should set SO=KEEPALIVE to 10000 by default', (done) => {
const ports = [];
let socket;
if (opts.clusterNodes) {
Object.values(db.redis.connectionPool.nodes.all).forEach(node => {
ports.push({ localPort: node.stream.localPort, remotePort: node.stream.remotePort });
});
const node = Object.values(db.redis.connectionPool.nodes.all).find(node => node.status === 'ready');
if (!node) {
return done(new Error('No ready node found'));
}
socket = node.stream;
} else {
ports.push({ localPort: db.redis.stream.localPort, remotePort: db.redis.stream.remotePort });
socket = db.redis.stream;
}
checkSocketOption(ports, 'SO=KEEPALIVE', 10000, 10, done);
getSockOptValue(socket, 'SO=KEEPALIVE', assertSockOpt(10000, 10, done) );
});

describe('when setting keepAlive option', () => {
Expand All @@ -200,16 +181,17 @@ module.exports.tests = (clientCreator, opts) => {

it('should set SO=KEEPALIVE to the value specified in the constructor config', (done) => {
const ports = [];
let socket;
if (opts.clusterNodes) {
Object.values(db.redis.connectionPool.nodes.all)
.filter(node => node.status === 'ready')
.forEach(node => {
ports.push({ localPort: node.stream.localPort, remotePort: node.stream.remotePort });
});
const node = Object.values(db.redis.connectionPool.nodes.all).find(node => node.status === 'ready');
if (!node) {
return done(new Error('No ready node found'));
}
socket = node.stream;
} else {
ports.push({ localPort: db.redis.stream.localPort, remotePort: db.redis.stream.remotePort });
socket = db.redis.stream;
}
checkSocketOption(ports, 'SO=KEEPALIVE', keepAliveValue, 10, done);
getSockOptValue(socket, 'SO=KEEPALIVE', assertSockOpt(5000, 10, done) );
});
});
});
Expand Down
54 changes: 54 additions & 0 deletions test/testutils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const { exec } = require('child_process');
const { getsockopt } = require('sockopt');

const getSockOptValue = (socket, opt, cb) => {
if (process.env.CI !== undefined) {
return linuxGetSockOptValue(socket, opt, cb);
}

return macosGetSockOptValue(socket, opt, cb);
};

const macosGetSockOptValue = (socket, opt, cb) => {
const pid = process.pid;
exec(`lsof -a -p ${pid} -i 4 -T f`, (error, stdout, stderr) => {
if (error) {
return cb(error);
}
if (stderr) {
return cb(new Error(stderr));
}

const keepAliveOption = stdout
.split('\n')
.find(line => line.includes(`:${socket.localPort}`) && line.includes(`:${socket.remotePort}`));

if (!keepAliveOption) {
cb(new Error(`no entry found for local port ${socket.localPort}, and remote port ${socket.remotePort}`));
}

if (!keepAliveOption.includes(opt)) {
cb(new Error(`${opt} option not found: ${keepAliveOption}`));
}

const keepAliveValue = parseInt(keepAliveOption.match(new RegExp(`${opt}=(\\d+)`))[1], 10);
cb(null, keepAliveValue);
});
};

const linuxGetSockOptValue = (socket, opt, cb) => {
const SOL_SOCKET = 0xffff;
const SOCK_OPTS = {
'SO=KEEPALIVE': 0x0008,
};
if (!SOCK_OPTS[opt]) {
return cb(new Error(`Unknown socket option: ${opt}`));
}

const keepAliveValue = getsockopt(socket, SOL_SOCKET, SOCK_OPTS[opt]);
cb(null, keepAliveValue);
};

module.exports = {
getSockOptValue
};

0 comments on commit b14048c

Please sign in to comment.