summaryrefslogtreecommitdiff
path: root/server.js
diff options
context:
space:
mode:
authorschneefux <schneefux+commit@schneefux.xyz>2017-04-13 12:59:18 +0200
committerschneefux <schneefux+commit@schneefux.xyz>2017-04-13 12:59:18 +0200
commit187c9da9855ef8759a3bd386177cc8eb8c76f147 (patch)
tree551a769427a18fd026c8c18412f7b735c8e79e16 /server.js
parentf9e179aad1d759184472d1020655e709a86b89ce (diff)
downloadbridge-187c9da9855ef8759a3bd386177cc8eb8c76f147.tar.gz
bridge-187c9da9855ef8759a3bd386177cc8eb8c76f147.zip
always call /players before updating
Diffstat (limited to 'server.js')
-rw-r--r--server.js142
1 files changed, 86 insertions, 56 deletions
diff --git a/server.js b/server.js
index 0f4def9..1ec7271 100644
--- a/server.js
+++ b/server.js
@@ -42,8 +42,7 @@ server.listen(8880);
app.use(express.static("assets"));
app.use(bodyParser.json());
-// request a grab job
-function requestUpdate(name, region, last_match_created_date, id) {
+function grabPlayer(name, region, last_match_created_date, id) {
last_match_created_date = last_match_created_date || new Date(value=0);
// add 1s, because createdAt-start <= x <= createdAt-end
@@ -60,59 +59,78 @@ function requestUpdate(name, region, last_match_created_date, id) {
}
};
console.log("requesting update for", name, region);
+
return ch.sendToQueue("grab", new Buffer(JSON.stringify(payload)),
{ persistent: true, type: "matches" });
}
+// search for a player name in one region
+// request process for lifetime
+// return an array (JSONAPI response)
+async function searchPlayerInRegion(region, name, id) {
+ let players = [],
+ found = false;
+ while (true) {
+ console.log("searching in", region, name, id);
+ try {
+ // find players by name
+ let opts = {
+ uri: "https://api.dc01.gamelockerapp.com/shards/" + region + "/players",
+ headers: {
+ "X-Title-Id": "semc-vainglory",
+ "Authorization": MADGLORY_TOKEN
+ },
+ qs: {},
+ json: true,
+ gzip: true
+ };
+ // prefer player id over name
+ if (id == undefined) opts["qs"]["filter[playerNames]"] = name
+ else opts["qs"]["filter[playerIds]"] = id
+ players = await request(opts);
+
+ console.log("found", name, region);
+ found = true;
+ break;
+ } catch (err) {
+ if (err.statusCode == 429) {
+ console.log("rate limited, sleeping");
+ await sleep(100); // no return, no break => retry
+ } else if (err.statusCode != 404) console.error(err);
+ if (err.statusCode != 429) {
+ console.log("failed", name, region, err.statusCode);
+ return;
+ }
+ }
+ }
+
+ if (!found) return [];
+
+ // players.length will be 1 in 99.9% of all cases
+ // - but this will cover the 0.01% too
+ //
+ // send to processor, so the player is in db
+ // no matter whether we find matches or not
+ await ch.sendToQueue("process", new Buffer(JSON.stringify(players.data)),
+ { persistent: true, type: "player" });
+
+ return players.data;
+}
+
// search for player name on all shards
+// grab player(s)
// send a notification for results and request updates
async function searchPlayer(name) {
let found = false;
- console.log("looking up", name);
+ console.log("searching up", name);
await Promise.all(REGIONS.map(async (region) => {
- let players = [];
- while (true) {
- console.log("looking up", name, region);
- try {
- // find players by name
- players = await request({
- uri: "https://api.dc01.gamelockerapp.com/shards/" + region + "/players",
- headers: {
- "X-Title-Id": "semc-vainglory",
- "Authorization": MADGLORY_TOKEN
- },
- qs: {
- "filter[playerNames]": name
- },
- json: true,
- gzip: true
- });
- console.log("found", name, region);
- break;
- } catch (err) {
- if (err.statusCode == 429) {
- console.log("rate limited, sleeping");
- await sleep(100); // no return, no break => retry
- } else if (err.statusCode != 404) console.error(err);
- if (err.statusCode != 429) {
- console.log("failed", name, region, err.statusCode);
- return;
- }
- }
- }
- // players.length will be 1 in 99.9% of all cases
- // - but this will cover the 0.01% too
- //
- // send to processor, so the player is in db
- // no matter whether we find matches or not
- await ch.sendToQueue("process", new Buffer(JSON.stringify(players.data)),
- { persistent: true, type: "player" });
+ let players = await searchPlayerInRegion(region, name, undefined);
+ if (players.length > 0)
+ found = true;
// request grab jobs
- await Promise.all(players.data.map((p) =>
- requestUpdate(p.attributes.name, p.attributes.shardId, undefined, p.id)));
-
- found = true;
+ await Promise.all(players.map((p) =>
+ grabPlayer(p.attributes.name, p.attributes.shardId, undefined, p.id)));
}));
// notify web
if (found)
@@ -123,20 +141,28 @@ async function searchPlayer(name) {
new Buffer("search_fail"));
}
-// update a player based on db record
-function updatePlayer(player) {
+// update a player from API based on db record
+// & grab player
+async function updatePlayer(player) {
// set last_update and request an update job
// if last_update is null, we need that player's full history
let grabstart;
if (player.get("last_update") == null) grabstart = undefined;
else grabstart = player.get("last_match_created_date");
- return Promise.all([
- player.update({ last_update: seq.fn("NOW") },
- { fields: ["last_update"] } ),
- requestUpdate(player.name, player.shard_id,
- grabstart, player.api_id)
- ]);
+ await player.update({ last_update: seq.fn("NOW") },
+ { fields: ["last_update"] } );
+
+ let players = await searchPlayerInRegion(
+ player.get("shard_id"), player.get("name"), player.get("api_id"));
+
+ // will be the same as `player` 99.9% of the time
+ // but not when the player changed their name
+ // search happened by ID, so we get only 1 player back
+ // but player.name != players[0].attributes.name
+ // (with a name change)
+ await Promise.all(players.map((p) =>
+ grabPlayer(p.attributes.name, p.attributes.shardId, grabstart, p.id)));
}
// update a region's samples since samples_last_update
@@ -174,21 +200,25 @@ async function updateSamples(region) {
/* routes */
// force an update
-app.post("/api/player/:name/search", (req, res) => {
+app.post("/api/player/:name/search", async (req, res) => {
searchPlayer(req.params.name); // do not await, just fire
res.sendStatus(204); // notifications will follow
});
// update a known user
+// flow:
+// * get from db
+// * update lifetime from `/players` via id, catch IGN changes
+// * update from `/matches`
app.post("/api/player/:name/update", async (req, res) => {
let player = await model.Player.findOne({ where: { name: req.params.name } });
if (player == undefined) {
console.log("player not found in db, searching instead", req.params.name);
- await searchPlayer(req.params.name);
+ searchPlayer(req.params.name); // fire away
res.sendStatus(204);
return;
}
console.log("player in db, updating", req.params.name);
- await updatePlayer(player);
+ updatePlayer(player); // fire away
res.sendStatus(204);
});
// crunch a known user
@@ -207,7 +237,7 @@ app.post("/api/player/:name/crunch", async (req, res) => {
// update a random user
app.post("/api/player", async (req, res) => {
let player = await model.Player.findOne({ order: [ Seq.fn("RAND") ] });
- await updatePlayer(player);
+ updatePlayer(player); // do not await
res.json(player);
});
// download sample sets