]>
Commit | Line | Data |
---|---|---|
60862425 | 1 | import * as Sequelize from 'sequelize' |
39445ead | 2 | import { isHostValid, logger } from '../../helpers' |
60862425 | 3 | import { FRIEND_SCORE, SERVERS_SCORE } from '../../initializers' |
39445ead C |
4 | import { addMethodsToModel } from '../utils' |
5 | import { ServerAttributes, ServerInstance, ServerMethods } from './server-interface' | |
60862425 C |
6 | |
7 | let Server: Sequelize.Model<ServerInstance, ServerAttributes> | |
39445ead | 8 | let updateServersScoreAndRemoveBadOnes: ServerMethods.UpdateServersScoreAndRemoveBadOnes |
60862425 C |
9 | |
10 | export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) { | |
11 | Server = sequelize.define<ServerInstance, ServerAttributes>('Server', | |
12 | { | |
13 | host: { | |
14 | type: DataTypes.STRING, | |
15 | allowNull: false, | |
16 | validate: { | |
17 | isHost: value => { | |
18 | const res = isHostValid(value) | |
19 | if (res === false) throw new Error('Host not valid.') | |
20 | } | |
21 | } | |
22 | }, | |
23 | score: { | |
24 | type: DataTypes.INTEGER, | |
25 | defaultValue: FRIEND_SCORE.BASE, | |
26 | allowNull: false, | |
27 | validate: { | |
28 | isInt: true, | |
29 | max: FRIEND_SCORE.MAX | |
30 | } | |
31 | } | |
32 | }, | |
33 | { | |
34 | indexes: [ | |
35 | { | |
36 | fields: [ 'host' ], | |
37 | unique: true | |
38 | }, | |
39 | { | |
40 | fields: [ 'score' ] | |
41 | } | |
42 | ] | |
43 | } | |
44 | ) | |
45 | ||
46 | const classMethods = [ | |
d4f1e94c | 47 | updateServersScoreAndRemoveBadOnes |
60862425 C |
48 | ] |
49 | addMethodsToModel(Server, classMethods) | |
50 | ||
51 | return Server | |
52 | } | |
53 | ||
54 | // ------------------------------ Statics ------------------------------ | |
55 | ||
39445ead | 56 | updateServersScoreAndRemoveBadOnes = function (goodServers: number[], badServers: number[]) { |
60862425 C |
57 | logger.info('Updating %d good servers and %d bad servers scores.', goodServers.length, badServers.length) |
58 | ||
59 | if (goodServers.length !== 0) { | |
60 | incrementScores(goodServers, SERVERS_SCORE.BONUS).catch(err => { | |
61 | logger.error('Cannot increment scores of good servers.', err) | |
62 | }) | |
63 | } | |
64 | ||
65 | if (badServers.length !== 0) { | |
66 | incrementScores(badServers, SERVERS_SCORE.PENALTY) | |
67 | .then(() => removeBadServers()) | |
68 | .catch(err => { | |
69 | if (err) logger.error('Cannot decrement scores of bad servers.', err) | |
70 | }) | |
71 | } | |
72 | } | |
73 | ||
74 | // --------------------------------------------------------------------------- | |
75 | ||
76 | // Remove servers with a score of 0 (too many requests where they were unreachable) | |
77 | async function removeBadServers () { | |
78 | try { | |
79 | const servers = await listBadServers() | |
80 | ||
81 | const serversRemovePromises = servers.map(server => server.destroy()) | |
82 | await Promise.all(serversRemovePromises) | |
83 | ||
84 | const numberOfServersRemoved = servers.length | |
85 | ||
86 | if (numberOfServersRemoved) { | |
87 | logger.info('Removed %d servers.', numberOfServersRemoved) | |
88 | } else { | |
89 | logger.info('No need to remove bad servers.') | |
90 | } | |
91 | } catch (err) { | |
92 | logger.error('Cannot remove bad servers.', err) | |
93 | } | |
94 | } | |
39445ead C |
95 | |
96 | function incrementScores (ids: number[], value: number) { | |
97 | const update = { | |
98 | score: Sequelize.literal('score +' + value) | |
99 | } | |
100 | ||
101 | const options = { | |
102 | where: { | |
103 | id: { | |
104 | [Sequelize.Op.in]: ids | |
105 | } | |
106 | }, | |
107 | // In this case score is a literal and not an integer so we do not validate it | |
108 | validate: false | |
109 | } | |
110 | ||
111 | return Server.update(update, options) | |
112 | } | |
113 | ||
114 | function listBadServers () { | |
115 | const query = { | |
116 | where: { | |
117 | score: { | |
118 | [Sequelize.Op.lte]: 0 | |
119 | } | |
120 | } | |
121 | } | |
122 | ||
123 | return Server.findAll(query) | |
124 | } |