Closed celalo closed 4 years ago
I don't think it is possible right now. What's the problem with 2 instance of redis? I never had to worry about no. of connection to redis.
You are right connection to redis is very very lightweight but it adds up if you need to open 10 connections with different prefixes in a lambda function that runs in sub 100ms. Also, the issue multiplies when you have a lot of concurrent lambda functions without being able to control container's life-cycle. Redis server ends up with hundreds of connections. It becomes a bit worrying.
I see. connection pooling is still problem in Lambda last i tried.
Right, another problem is if you have a cap on the number of connections limit. I'm using a free redis instance from redislabs.com which has 30 as a max number of connections. I connect to it via an AWS lambda through an apollo graphql server. So I'm facing a similar issue where I hit the 30 connections limit even though no one is using the endpoint besides 2/3 developers. https://github.com/apollographql/apollo-server/issues/3434
This issue has been automatically marked as stale because it has not had recent activity. It will be closed after 7 days if no further activity occurs, but feel free to re-open a closed issue if needed.
We looked into this, and it looks like this is exactly what refix provided. Albeit refix
is old and unmaintained (and also written in CoffeeScript) → a new approach would be to use @ioredis/commands
. We ultimately didn't go this approach, but here's how you would do it – this has been tested ✅ :
const commands = require('@ioredis/commands');
const Redis = require('ioredis-mock'); // or `require('ioredis')`
// create your redis instance
const client = new Redis();
// modern approach inspired by `refix` package
// <https://github.com/luin/ioredis/issues/983#issuecomment-1448839874>
function refix(client, prefix) {
const proxy = {};
Object.setPrototypeOf(proxy, client);
for (const command of commands.list) {
proxy[command] = function (...args) {
const keyIndexes = commands.getKeyIndexes(command, args);
for (const index of keyIndexes) {
args[index] = prefix + args[index];
}
return client[command](...args);
};
}
return proxy;
}
// create a new instance with refix
const prefixedInstance = refix(client, 'foo:'); // will prepend all keys with "foo:" prefix
prefixedInstance.set('hello', 'world'); // sets "foo:hello" to "world"
This was research done for :tangerine: Tangerine for @forwardemail.
Previous comment updated with working and tested example ✅
Slight improvement to support mset
and mget
via Map
or Object
:
// modern approach inspired by `refix` package
// <https://github.com/luin/ioredis/issues/983#issuecomment-1448839874>
// <https://github.com/luin/ioredis/issues/983#issuecomment-1536728696>
function refix(client, prefix) {
const proxy = {};
Object.setPrototypeOf(proxy, client);
for (const command of commands.list) {
proxy[command] = function (...args) {
const keyIndexes = commands.getKeyIndexes(command, args);
for (const index of keyIndexes) {
if (args[index] instanceof Map) {
const map = new Map();
for (const [key, value] of args[index]) {
map.set(prefix + key, value);
}
args[index] = map;
} else if (
typeof args[index] === 'object' &&
!Array.isArray(args[index])
) {
const obj = {};
for (const key of Object.keys(args[index])) {
obj[prefix + key] = args[index][key];
}
args[index] = obj;
} else {
args[index] = prefix + args[index];
}
}
return client[command](...args);
};
}
return proxy;
}
You can use native Proxy by Javascript instead
function refix(client, prefix) {
return new Proxy(client, {
get(target, prop, receiver) {
if (prop === 'options') {
return {
...target.options,
keyPrefix: prefix,
};
}
return Reflect.get(target, prop, receiver);
},
});
}
Maybe something like this?