<commit_before>import { PlayerInfo, Player, PlayerGameInfo, GameType, GameTypes } from 'hive-api';
import { Stats } from '../Stats';
import { Updater } from 'lergins-bot-framework';

export type PlayerInfoUpdateFunction = (playerInfo: PlayerInfo, player: Player) => void;
export type PlayerGameInfoUpdateFunction = (gameType: GameType, gameInfo: PlayerGameInfo, player: Player) => void;
export type PlayerGameInfosUpdateFunction = (gameInfos: Map<GameType, PlayerGameInfo>, player: Player, playerInfo: PlayerInfo) => void;

export class UpdateService {
  private static playerInfoUpdater: Set<PlayerInfoUpdateFunction> = new Set();
  private static playerGameInfoUpdater: Set<PlayerGameInfoUpdateFunction> = new Set();
  private static playerGameInfosUpdater: Set<{ types: GameType[], func: PlayerGameInfosUpdateFunction, lastCalls: Map<string, number> }> = new Set();

  private static playerGameInfosCache: Map<string, Map<GameType, PlayerGameInfo>> = new Map();
  private static playerInfoCache: Map<string, PlayerInfo> = new Map();

  /**
   * registers a function to be called everytime the infos of a player are updated
   * @param updateFunction function that is called with each update
   */
  static registerPlayerInfoUpdater(updateFunction: PlayerInfoUpdateFunction, name = updateFunction.name){
    console.log(`Registered PlayerInfoUpdater: ${name}`)
    UpdateService.playerInfoUpdater.add(updateFunction);
  }

  /**
   * requests an update of the player infos, after the update has happened all functions registered with registerPlayerInfoUpdater will be called with the new infos
   */
  static requestPlayerInfoUpdate(player: Player, maxCacheAge: number = 60 * 60 * 1000){
    return player
      .info(maxCacheAge)
      .then( info => {
        Stats.track('player-info');

        UpdateService.playerInfoUpdater.forEach(
          updater => updater(info, player)
        );

        UpdateService.playerInfoCache.set(player.uuid, info);

        UpdateService.sendPlayerGameInfosUpdates(player);
      })
      .catch(err => {
        if (err.name === "FetchError") {
          return new Promise((resolve, reject) => {
            Stats.track('fetch-error-player-info');

            setTimeout(() => {
              resolve(UpdateService.requestPlayerInfoUpdate(player, maxCacheAge));
            }, 60000);
          });
        } else {
          Updater.sendError(err, `player/${player.uuid}`);
        }
      });
  }

  static registerPlayerGameInfoUpdater(updateFunction: PlayerGameInfoUpdateFunction, name = updateFunction.name){
    console.log(`Registered PlayerGameInfoUpdater: ${name}`);
    UpdateService.playerGameInfoUpdater.add(updateFunction);
  }

  static registerPlayerGameInfosUpdater(gameTypes: GameType[], updateFunction: PlayerGameInfosUpdateFunction, name = updateFunction.name){
    console.log(`Registered PlayerGameInfosUpdater: ${name}`);
    UpdateService.playerGameInfosUpdater.add({ types: gameTypes, func: updateFunction, lastCalls: new Map() });
  }

  static registerAllPlayerGameInfosUpdater(updateFunction: PlayerGameInfosUpdateFunction, name = updateFunction.name){
    console.log(`Registered AllPlayerGameInfosUpdater: ${name}`);
    UpdateService.playerGameInfosUpdater.add({ types: GameTypes.list, func: updateFunction, lastCalls: new Map() });
  }

  static requestPlayerGameInfoUpdate(gameType: GameType, player: Player, maxCacheAge: number = 60 * 60 * 1000){
    return player
      .gameInfo(gameType, maxCacheAge)
      .then( info => {
        Stats.track('player-info-gametype');
        
        UpdateService.playerGameInfoUpdater.forEach(
          updater => updater(gameType, info, player)
        );

        UpdateService.updatePlayerGameInfosCache(gameType, player, info);
      })
      .catch(err => {
        if (err.name === "FetchError") {
          return new Promise((resolve, reject) => {
            Stats.track('fetch-error-player-game-info');

            setTimeout(() => {
              resolve(UpdateService.requestPlayerGameInfoUpdate(gameType, player, maxCacheAge));
            }, 60000);
          });
        } else {
          Updater.sendError(err, `player/${player.uuid}/${gameType.id}`);
        }
      });
  }

  static requestPlayerGameInfosUpdate(gameTypes: GameType[], player: Player, maxCacheAge: number = 60 * 60 * 1000){
    UpdateService.requestPlayerInfoUpdate(player, 1000 * 60 * 60 * 24 * 30); // we just need to make sure it is in the cache
    
    return gameTypes.map(gameType => 
      UpdateService.requestPlayerGameInfoUpdate(gameType, player, maxCacheAge)
    );
  }<commit_msg>removed retries as these would stack<commit_after>import { PlayerInfo, Player, PlayerGameInfo, GameType, GameTypes } from 'hive-api';
import { Stats } from '../Stats';
import { Updater } from 'lergins-bot-framework';

export type PlayerInfoUpdateFunction = (playerInfo: PlayerInfo, player: Player) => void;
export type PlayerGameInfoUpdateFunction = (gameType: GameType, gameInfo: PlayerGameInfo, player: Player) => void;
export type PlayerGameInfosUpdateFunction = (gameInfos: Map<GameType, PlayerGameInfo>, player: Player, playerInfo: PlayerInfo) => void;

export class UpdateService {
  private static playerInfoUpdater: Set<PlayerInfoUpdateFunction> = new Set();
  private static playerGameInfoUpdater: Set<PlayerGameInfoUpdateFunction> = new Set();
  private static playerGameInfosUpdater: Set<{ types: GameType[], func: PlayerGameInfosUpdateFunction, lastCalls: Map<string, number> }> = new Set();

  private static playerGameInfosCache: Map<string, Map<GameType, PlayerGameInfo>> = new Map();
  private static playerInfoCache: Map<string, PlayerInfo> = new Map();

  /**
   * registers a function to be called everytime the infos of a player are updated
   * @param updateFunction function that is called with each update
   */
  static registerPlayerInfoUpdater(updateFunction: PlayerInfoUpdateFunction, name = updateFunction.name){
    console.log(`Registered PlayerInfoUpdater: ${name}`)
    UpdateService.playerInfoUpdater.add(updateFunction);
  }

  /**
   * requests an update of the player infos, after the update has happened all functions registered with registerPlayerInfoUpdater will be called with the new infos
   */
  static requestPlayerInfoUpdate(player: Player, maxCacheAge: number = 60 * 60 * 1000){
    return player
      .info(maxCacheAge)
      .then( info => {
        Stats.track('player-info');

        UpdateService.playerInfoUpdater.forEach(
          updater => updater(info, player)
        );

        UpdateService.playerInfoCache.set(player.uuid, info);

        UpdateService.sendPlayerGameInfosUpdates(player);
      })
      .catch(err => {
        if (err.name === "FetchError") {
          return new Promise((resolve, reject) => {
            Stats.track('fetch-error-player-info');
/*
            setTimeout(() => {
              resolve(UpdateService.requestPlayerInfoUpdate(player, maxCacheAge));
            }, 60000);*/
          });
        } else {
          Updater.sendError(err, `player/${player.uuid}`);
        }
      });
  }

  static registerPlayerGameInfoUpdater(updateFunction: PlayerGameInfoUpdateFunction, name = updateFunction.name){
    console.log(`Registered PlayerGameInfoUpdater: ${name}`);
    UpdateService.playerGameInfoUpdater.add(updateFunction);
  }

  static registerPlayerGameInfosUpdater(gameTypes: GameType[], updateFunction: PlayerGameInfosUpdateFunction, name = updateFunction.name){
    console.log(`Registered PlayerGameInfosUpdater: ${name}`);
    UpdateService.playerGameInfosUpdater.add({ types: gameTypes, func: updateFunction, lastCalls: new Map() });
  }

  static registerAllPlayerGameInfosUpdater(updateFunction: PlayerGameInfosUpdateFunction, name = updateFunction.name){
    console.log(`Registered AllPlayerGameInfosUpdater: ${name}`);
    UpdateService.playerGameInfosUpdater.add({ types: GameTypes.list, func: updateFunction, lastCalls: new Map() });
  }

  static requestPlayerGameInfoUpdate(gameType: GameType, player: Player, maxCacheAge: number = 60 * 60 * 1000){
    return player
      .gameInfo(gameType, maxCacheAge)
      .then( info => {
        Stats.track('player-info-gametype');
        
        UpdateService.playerGameInfoUpdater.forEach(
          updater => updater(gameType, info, player)
        );

        UpdateService.updatePlayerGameInfosCache(gameType, player, info);
      })
      .catch(err => {
        if (err.name === "FetchError") {
          return new Promise((resolve, reject) => {
            Stats.track('fetch-error-player-game-info');
/*
            setTimeout(() => {
              resolve(UpdateService.requestPlayerGameInfoUpdate(gameType, player, maxCacheAge));
            }, 60000);*/
          });
        } else {
          Updater.sendError(err, `player/${player.uuid}/${gameType.id}`);
        }
      });
  }

  static requestPlayerGameInfosUpdate(gameTypes: GameType[], player: Player, maxCacheAge: number = 60 * 60 * 1000){
    UpdateService.requestPlayerInfoUpdate(player, 1000 * 60 * 60 * 24 * 30); // we just need to make sure it is in the cache
    
    return gameTypes.map(gameType => 
      UpdateService.requestPlayerGameInfoUpdate(gameType, player, maxCacheAge)
    );
  }
{'fraction_non_alphanumeric': 0.11328928842196469, 'fraction_numerical': 0.009964258637495938, 'mean_word_length': 3.740246406570842, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '638213', 'n_tokens_mistral': 2645, 'n_tokens_neox': 2570, 'n_words': 601}