Security News
GitHub Removes Malicious Pull Requests Targeting Open Source Repositories
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
redis-rank
Advanced tools
Back-end to generate and manage leaderboards using Redis. Written in TypeScript and Promise-based.
Back-end to generate and manage leaderboards using Redis. Written in TypeScript and Promise-based.
All the library is promise based.
EVAL
and MULTI
.Planned features:
$ npm install redis-rank
Redis 2.6.12 or newer is required. Packages ioredis and moment are dependencies.
First import/require ioredis
and redis-rank
.
ES5
const Redis = require('ioredis');
const RedisRank = require('redis-rank');
const Leaderboard = RedisRank.Leaderboard;
ES6
import { Redis } from 'ioredis';
import { Leaderboard } from 'redis-rank';
Then create a Leaderboard. You will have to provide a ioredis connection object. See here for more information on how to set it up.
// setup connection
let ioredis_client = new Redis({
host: "127.0.0.1",
port: 6379
});
// create a leaderboard
let lb = new Leaderboard(ioredis_client, {
/* optional options */
// redis key to store the sorted set
path: "lb",
// inverse leaderboard: true if lower scores are better
lowToHigh: false
});
All the methods listed here are promises.
// add entries
lb.add("alice", 25);
lb.add("bob", 13);
lb.add("dave", 42);
lb.add("eve", 54);
// update entries
lb.add("bob", 27); // replace score
lb.incr("alice", 10); // increment by 10, now 35
lb.incr("dave", -5); // decrement by 5, now 37
// remove entries
lb.remove("eve"); // eve is no more
// count entries
lb.total(); // number of entries stored: 3
// query entries
lb.peek("bob"); // { id: "bob", score: 27, rank: 2 }
lb.score("dave"); // dave's score: 37
lb.rank("alice"); // alice's rank: 3
lb.at(1); // get entry at a specific rank: { id: "dave", ... }
// list entries
// all of these return an array of entries
// something like [{ id: "...", score: xxx, rank: xx }, ...]
lb.list(5, 10); // entries between ranks 5 and 10 inclusive
lb.top(10); // the top 10 entries. Alias for list(1, max)
lb.around("id", 10); // get 10 entries above and below the queried entry
lb.around("id", 10, true); // pass true to make sure you get 10+1+10 entries even near the borders
// remove all entries
lb.clear();
Note: most of the methods will return null
if the entry is not found.
let plb = new PeriodicLeaderboard(redis, {
/* optional options */
// base key to store the leaderboards (plb:<time key>)
path: "plb",
// leaderboard cycle
timeFrame: 'all-time', // 'minute' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'all-time'
// you can also provide a custom function to evaluate the current time
now(): () => new Date(),
leaderboardOptions: { // LeaderboardOptions
lowToHigh: false,
...
}
});
Then every time you need it, call getCurrent
to get the corresponding Leaderboard for the current time.
let lb = plb.getCurrent();
// now use lb as any other Leaderboard
lb.add("pepe", 99);
lb.top(10);
// etc
A matrix of leaderboards is defined by its dimensions and features. A dimension represents an abstract group (global, region, map) asocciated with a time frame (all-time, weekly). A feature is a kind of leaderboad and score, for example, a basic numeric score, the number of kills, most seconds survived, etc.
Let's say we want to create a leaderboard for a game with 5 dimensions:
all-time
leaderboardmonthly
, weekly
, daily
: dynamic, periodic leaderboardsall-time
, country specific leaderboardAnd some features, lets say:
The leaderboard matrix for the game would look like this:
kills | coins | time | |
---|---|---|---|
global | ... | ... | ... |
monthly | ... | ... | ... |
weekly | ... | ... | ... |
daily | ... | ... | ... |
US | ... | ... | ... |
And in code, this looks like:
let mlb = new LeaderboardMatrix(redis, {
path: 'mygame',
dimensions: [{
name: 'global',
timeFrame: 'all-time'
}, {
name: 'monthly',
timeFrame: 'monthly'
}, {
name: 'weekly',
timeFrame: 'weekly'
}, {
name: 'daily',
timeFrame: 'daily'
}, {
name: 'US',
timeFrame: 'all-time'
}],
features: [{
name: 'kills'
}, {
name: 'coins'
}, {
name: 'time',
options: { lowToHigh: true }
}]
});
To add a new entry for the leaderboards you don't have to retrieve every leaderboard and call add
on each one. You can use the add
function of the LeaderboardMatrix
object:
mlb.add( // returns a promise
"pepe", // id
{
// features
// you can list some or all of them
// if you skip some features the corresponding
// columns will be ignored
kills: 36,
coins: 92,
time: 342
}, [
// dimensions
// also you can skip dimensions if they don't apply
'global',
'monthly',
'weekly',
'daily',
// this is not an US player so don't add it to that row
//'US'
]
);
// also incr works
mlb.incr(
"pepe",
{
kills: 3,
coins: 5,
time: 9
}, [
'global',
'monthly',
'weekly',
'daily',
]
);
To list entries within the matrix, yo can use top
and around
based on a dimension like this:
lm.top('weekly', 'kills', 3);
// example
[
{ id: 'pepe', rank: 1, kills: 36, coins: 92, time: 342 },
{ id: '....', rank: 2, kills: 27, coins: 123, time: 295 },
{ id: '....', rank: 3, kills: 16, coins: 77, time: 420 }
]
// also
lm.around('monthly', 'time', pepe, 15);
To access a single leaderboard you can use the get
function:
let lb = mlb.get('global', 'kills');
if(lb) { // may be null if the dimension/feature is invalid
// use lb as any other Leaderboard
lb.top(10);
}
You can peek at the documented code for more information.
TypeScript definitions are available.
A Redis server with default configuration is expected in localhost. Note: The database will be flushed.
$ npm test
I tried with ioredis-mock but it has some problems with lua scripts.
MIT. See LICENSE.
FAQs
Manage real-time leaderboards using Redis
The npm package redis-rank receives a total of 0 weekly downloads. As such, redis-rank popularity was classified as not popular.
We found that redis-rank demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.