-
Notifications
You must be signed in to change notification settings - Fork 568
/
Copy pathr-srankmanager.coffee
127 lines (102 loc) · 4.48 KB
/
r-srankmanager.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
Promise = require 'bluebird'
moment = require 'moment'
Logger = require '../../app/common/logger.coffee'
config = require '../../config/config.js'
env = config.get("env")
ttl = config.get("redis.ttl")
generatePushID = require '../../app/common/generate_push_id'
zlib = Promise.promisifyAll(require 'zlib')
# Helper returns the SRank Ladder Redis key prefix
keyPrefix = () ->
if not RedisSRankManager.unitTestMode
return "#{env}:s_rank_ladder:"
else
return "#{env}:s_rank_ladder:test:"
seasonKey = (seasonStartMoment) ->
return seasonStartMoment.format("YYYY_MM")
expireAtTimeForSeasonStart = (seasonStartMoment) ->
if not RedisSRankManager.unitTestMode
startOfNextSeasonMoment = seasonStartMoment.clone().add(1,"month")
# add a single day for overlap
startOfNextSeasonMoment.add(1,"day")
return startOfNextSeasonMoment.valueOf()
else
return moment.utc().add(1,"hour").valueOf()
###*
# Class 'RedisSRankManager'
# Manages storage of srank ladder ratings/position in Redis
# ttl sets the expiration time of keys, defaults to 72 hours
###
class RedisSRankManager
@unitTestMode: false # This will change the way timeouts are handled so different seasons can be unit tested
###*
# Constructor
# @param {Object} redis, a promisified redis connection
###
constructor: (redis, opts = {}) ->
@redis = redis
return
###*
# Updates the ladder rating of a player by user id
# @param {String} userId user id being updated
# @param {Moment} seasonStartMoment moment representing the start of the month of the season
# @param {Integer} ladderRating players new ladder rating
# @return {Promise}
###
updateUserLadderRating: (userId,seasonStartMoment, ladderRating) ->
Logger.module("REDIS").debug "updateUserLadderRating() -> updating Ladder Rating for player #{userId} to #{ladderRating}"
redisSeasonKey = keyPrefix() + seasonKey(seasonStartMoment)
multi = @redis.multi() # start a multi command
multi.zadd(redisSeasonKey, ladderRating, userId)
multi.expireat(redisSeasonKey, expireAtTimeForSeasonStart(seasonStartMoment))
return multi.execAsync()
###*
# Retrieves player's srank ladder position
# @param {String} userId user id being updated
# @param {Moment} seasonStartMoment moment representing the start of the month of the season
# @return {Promise} Resolves to a integer for players ladder position
###
getUserLadderPosition: (userId,seasonStartMoment) ->
Logger.module("REDIS").debug "updateUserLadderRating() -> getting Ladder Position for #{userId}"
redisSeasonKey = keyPrefix() + seasonKey(seasonStartMoment)
return @redis.zrevrankAsync(redisSeasonKey, userId)
.then (ladderPosition) ->
if ladderPosition?
return Promise.resolve(parseInt(ladderPosition)+1)
else
return Promise.resolve(null)
###*
# Gets top srank ladder player ids
# @param {moment} seasonStartMoment moment for the start of season being retrieved
# @param {integer} numPlayers
# @return {Promise} An array of user ids in order of top players
###
getTopLadderUserIds: (seasonStartMoment, numPlayers) ->
Logger.module("REDIS").debug "getTopLadderUserIds() -> retrieving top #{numPlayers} s-rank players for season #{seasonKey(seasonStartMoment)}"
redisSeasonKey = keyPrefix() + seasonKey(seasonStartMoment)
return @redis.zrevrangeAsync(redisSeasonKey, 0, numPlayers-1)
###*
# Synchronous - Returns true/false whethere a season's ratings can still be found in Redis
# @param {moment} seasonStartMoment moment for the start of season being retrieved
# @param {moment} systemTime current time of the system
# @return {boolean} Whether provided season's data is active in Redis
###
getSeasonIsStillActiveInRedis: (seasonStartMoment, systemTime) ->
seasonExpireMoment = moment.utc(expireAtTimeForSeasonStart(seasonStartMoment))
return seasonExpireMoment.isAfter(systemTime)
###*
# This method has no use in normal user flow, it's only purpose is QA and wiping a user
# @param {String} userId user id being removed
# @param {Moment} seasonStartMoment moment representing the start of the month of the season
# @return {Promise} Promise that returns on operation completion, no value
###
_removeUserFromLadder: (userId, seasonStartMoment) ->
Logger.module("REDIS").debug "updateUserLadderRating() -> getting Ladder Position for #{userId}"
redisSeasonKey = keyPrefix() + seasonKey(seasonStartMoment)
return @redis.zremAsync(redisSeasonKey,userId)
###*
# Export a factory
###
module.exports = exports = (redis, opts) ->
SRankManager = new RedisSRankManager(redis, opts)
return SRankManager