Skip to content

Commit

Permalink
Added new profile endpoint to graphql
Browse files Browse the repository at this point in the history
* Also refactored populatePlayers code & added 30 day expiration to profile cache data, as well as a `updated_at` field
  • Loading branch information
builder-247 authored and ChristianDobbie committed Jan 10, 2022
1 parent 87d818b commit cddd130
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 39 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"engines": {
"node": ">=10"
},
"jshintConfig":{
"jshintConfig": {
"esversion": 10
}
}
6 changes: 6 additions & 0 deletions routes/graphql.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ class PlayersResolver {
});
}

async profile({ player_name }) {
const uuid = await getUUID(player_name);
const [{ profile }] = await populatePlayers([{ uuid }]);
return profile;
}

async status({ player_name }) {
return buildPlayerStatus(player_name);
}
Expand Down
24 changes: 23 additions & 1 deletion routes/spec.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,16 @@ type PlayerQuery {
"""
player_name: String!
): PlayerStatus

"""
Returns cached basic information about a player.
"""
profile(
"""
Username or non-dashed UUID of player. UUID should be used when feasible for better performance.
"""
player_name: String!
): PlayerProfile
}

type SkyblockQuery {
Expand Down Expand Up @@ -357,7 +367,7 @@ type SkyblockQuery {
events: String

"""
Date from which to get events. Uses a
Date from which to get events. Uses a
[custom date string](https://github.com/slothpixel/core/wiki/Using-custom-date-parameters).
E.g. to get past 24 hours, use `now-1d`.
"""
Expand Down Expand Up @@ -2433,6 +2443,18 @@ type PlayerStatus {
game: PlayerStatusGame
}

type PlayerProfile {
uuid: String
username: String
first_login: Float
last_login: Float
level: Float
achievement_points: Int
karma: Int
rank_formatted: String
updated_at: Float
}

type Quick_status {
buyMovingWeek: Int
buyOrders: Int
Expand Down
39 changes: 14 additions & 25 deletions store/buildPlayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,34 +56,23 @@ async function getPlayer(name) {
}
}

async function populatePlayers(players) {
return async.map(players, async (player) => {
/*
* Replaces player uuid fields with basic data
*/
async function populatePlayers(players = []) {
return Promise.all(players.map(async (player) => {
let profile = null;
const { uuid } = player;
try {
const [profile, isCached] = await pify(getPlayerProfile, {
multiArgs: true,
})(uuid);
if (profile === null) {
logger.debug(`[populatePlayers] ${uuid} not found in DB, generating...`);
const newPlayer = await buildPlayer(uuid);
delete player.uuid;
const profile = getPlayerFields(newPlayer);
profile.uuid = uuid;
player.profile = profile;
await cachePlayerProfile(profile);
return player;
}
delete player.uuid;
player.profile = profile;
if (isCached) {
return player;
}
delete player.uuid;
profile = await getPlayerProfile(uuid);
if (profile === null) {
logger.debug(`[populatePlayers] ${uuid} not found in DB, generating...`);
profile = getPlayerFields(await buildPlayer(uuid, { shouldCache: false }));
await cachePlayerProfile(profile);
return player;
} catch (error) {
logger.error(error);
}
});
player.profile = profile;
return player;
}));
}

module.exports = {
Expand Down
26 changes: 14 additions & 12 deletions store/queries.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,30 @@ const lbTemplates = require('./lbTemplates');

async function cachePlayerProfile(profile) {
const key = `profile:${profile.uuid}`;
profile.updated_at = Date.now();
logger.debug(`Caching ${key}`);
try {
await redis.set(key, JSON.stringify(profile));
await redis.setex(key, 30 * 24 * 60 * 60, JSON.stringify(profile));
} catch (error) {
logger.error(error);
}
return profile;
}

function getPlayerProfile(uuid, callback) {
async function getPlayerProfile(uuid) {
let reply = null;
const key = `profile:${uuid}`;
logger.debug(`Trying to get profile ${uuid} from cache`);
redis.get(key, (error, reply) => {
if (error) {
logger.error(error);
}
if (reply) {
logger.debug(`Cache hit for profile ${uuid}`);
return callback(error, JSON.parse(reply), true);
}
return callback(null, null, false);
});
try {
reply = await redis.get(key);
} catch (error) {
logger.error(`Failed to get profile: ${error}`);
}
if (reply) {
logger.debug(`Cache hit for profile ${uuid}`);
return JSON.parse(reply);
}
return reply;
}

function getMetadata(request, callback) {
Expand Down

0 comments on commit cddd130

Please sign in to comment.