summaryrefslogtreecommitdiff
path: root/service_crunch.js
diff options
context:
space:
mode:
Diffstat (limited to 'service_crunch.js')
-rw-r--r--service_crunch.js133
1 files changed, 133 insertions, 0 deletions
diff --git a/service_crunch.js b/service_crunch.js
new file mode 100644
index 0000000..bc8d06b
--- /dev/null
+++ b/service_crunch.js
@@ -0,0 +1,133 @@
+#!/usr/bin/env node
+/* jshint esnext: true */
+"use strict";
+
+const Promise = require("bluebird"),
+ Service = require("./service_skeleton.js");
+
+const logger = global.logger,
+ CRUNCH_QUEUE = process.env.CRUNCH_QUEUE || "crunch",
+ CRUNCH_TOURNAMENT_QUEUE = process.env.CRUNCH_TOURNAMENT_QUEUE || "crunch_tournament",
+ SHOVEL_SIZE = parseInt(process.env.SHOVEL_SIZE) || 1000;
+
+module.exports = class Cruncher extends Service {
+ constructor() {
+ super();
+
+ this.setTargets({
+ "regular": CRUNCH_QUEUE,
+ "tournament": CRUNCH_TOURNAMENT_QUEUE
+ });
+
+ this.setRoutes({
+ // crunch global meta
+ "/api/crunch/:category*?": async (req, res) => {
+ this.crunchGlobal(req.params.category || "regular");
+ res.sendStatus(204);
+ },
+ // crunch a player
+ "/api/player/:name/crunch/:category*?": async (req, res) => {
+ const category = req.params.category || "regular",
+ db = this.getDatabase(req.params.category || "regular"),
+ players = await db.Player.findAll({ where: { name: req.params.name } });
+ if (players == undefined) {
+ logger.error("player not found in db, won't crunch",
+ { name: req.params.name });
+ res.sendStatus(404);
+ return;
+ }
+ logger.info("player in db, crunching", { name: req.params.name });
+ players.forEach((player) =>
+ this.crunchPlayer(category, player.api_id)); // fire away
+ res.sendStatus(204);
+ },
+ // crunch a team
+ "/api/team/:id/crunch": async (req, res) => {
+ const db = this.getDatabase("regular"),
+ team = await db.Team.findOne({ where: { id: req.params.id } });
+ if (team == undefined) {
+ logger.error("team not found in db, won't crunch",
+ { name: req.params.id });
+ res.sendStatus(404);
+ return;
+ }
+ logger.info("team in db, crunching", { name: team.id });
+ crunchTeam(team.id); // fire away
+ res.sendStatus(204);
+ }
+ });
+ }
+
+ // upcrunch player's stats
+ async crunchPlayer(category, api_id) {
+ const db = this.getDatabase(category),
+ where = { player_api_id: api_id },
+ last_crunch = await db.PlayerPoint.findOne({
+ attributes: ["updated_at"],
+ where,
+ order: [ ["updated_at", "DESC"] ]
+ });
+ if (last_crunch) where.created_at = { $gt: last_crunch.updated_at };
+
+ // get all participants for this player
+ const participations = await db.Participant.findAll({
+ attributes: ["api_id"],
+ where
+ });
+ // send everything to cruncher
+ logger.info("sending participations to cruncher",
+ { length: participations.length });
+ await Promise.map(participations, async (p) =>
+ await this.forward(this.getQueue(category),
+ p.api_id, { persistent: true, type: "player" }));
+ // jobs with the type "player" won't be taken into account for global stats
+ // global stats would increase on every player refresh otherwise
+ }
+
+ // reset fame and crunch
+ // TODO: incremental crunch possible?
+ async crunchTeam(team_id) {
+ await this.forward(CRUNCH_QUEUE, team_id,
+ { persistent: true, type: "team" });
+ }
+
+ // crunch global stats
+ async crunchGlobal(category) {
+ const db = this.getDatabase(category);
+ // get lcpid from keys table
+ let last_crunch_participant_id = await this.getKey(db,
+ "global_last_crunch_participant_id", 0);
+
+ // don't load the whole Participant table at once into memory
+ let participations;
+
+ logger.info("loading all participations into cruncher",
+ { last_crunch_participant_id: last_crunch_participant_id });
+ do {
+ participations = await db.Participant.findAll({
+ attributes: ["api_id", "id"],
+ where: {
+ id: { $gt: last_crunch_participant_id }
+ },
+ limit: SHOVEL_SIZE,
+ order: [ ["id", "ASC"] ]
+ });
+ await Promise.map(participations, async (p) =>
+ await this.forward(this.getQueue(category), p.api_id,
+ { persistent: true, type: "global" }));
+
+ // update lpcid & refetch
+ if (participations.length > 0) {
+ last_crunch_participant_id = participations[participations.length-1].id;
+ await this.setKey(db, "global_last_crunch_participant_id",
+ last_crunch_participant_id);
+ }
+ logger.info("loading more participations into cruncher", {
+ limit: SHOVEL_SIZE,
+ size: participations.length,
+ last_crunch_participant_id: last_crunch_participant_id
+ });
+ } while (participations.length == SHOVEL_SIZE);
+ logger.info("done loading participations into cruncher");
+ }
+}