]>
Commit | Line | Data |
---|---|---|
60862425 | 1 | import * as Sequelize from 'sequelize' |
3fd3ab2d | 2 | import { AllowNull, Column, CreatedAt, Default, Is, IsInt, Max, Model, Table, UpdatedAt } from 'sequelize-typescript' |
3fd3ab2d | 3 | import { isHostValid } from '../../helpers/custom-validators/servers' |
da854ddd | 4 | import { logger } from '../../helpers/logger' |
c60774b0 | 5 | import { SERVERS_SCORE } from '../../initializers' |
3fd3ab2d | 6 | import { throwIfNotValid } from '../utils' |
60862425 | 7 | |
3fd3ab2d C |
8 | @Table({ |
9 | tableName: 'server', | |
10 | indexes: [ | |
60862425 | 11 | { |
3fd3ab2d C |
12 | fields: [ 'host' ], |
13 | unique: true | |
60862425 C |
14 | }, |
15 | { | |
3fd3ab2d | 16 | fields: [ 'score' ] |
60862425 | 17 | } |
60862425 | 18 | ] |
3fd3ab2d C |
19 | }) |
20 | export class ServerModel extends Model<ServerModel> { | |
21 | ||
22 | @AllowNull(false) | |
23 | @Is('Host', value => throwIfNotValid(value, isHostValid, 'valid host')) | |
24 | @Column | |
25 | host: string | |
26 | ||
27 | @AllowNull(false) | |
28 | @Default(SERVERS_SCORE.BASE) | |
29 | @IsInt | |
e8e12200 | 30 | @Max(SERVERS_SCORE.MAX) |
3fd3ab2d C |
31 | @Column |
32 | score: number | |
33 | ||
34 | @CreatedAt | |
35 | createdAt: Date | |
36 | ||
37 | @UpdatedAt | |
38 | updatedAt: Date | |
39 | ||
40 | static updateServersScoreAndRemoveBadOnes (goodServers: number[], badServers: number[]) { | |
41 | logger.info('Updating %d good servers and %d bad servers scores.', goodServers.length, badServers.length) | |
42 | ||
43 | if (goodServers.length !== 0) { | |
44 | ServerModel.incrementScores(goodServers, SERVERS_SCORE.BONUS) | |
45 | .catch(err => { | |
46 | logger.error('Cannot increment scores of good servers.', err) | |
47 | }) | |
48 | } | |
60862425 | 49 | |
3fd3ab2d C |
50 | if (badServers.length !== 0) { |
51 | ServerModel.incrementScores(badServers, SERVERS_SCORE.PENALTY) | |
52 | .then(() => ServerModel.removeBadServers()) | |
53 | .catch(err => { | |
54 | if (err) logger.error('Cannot decrement scores of bad servers.', err) | |
55 | }) | |
60862425 | 56 | |
3fd3ab2d | 57 | } |
60862425 | 58 | } |
60862425 | 59 | |
3fd3ab2d C |
60 | // Remove servers with a score of 0 (too many requests where they were unreachable) |
61 | private static async removeBadServers () { | |
62 | try { | |
63 | const servers = await ServerModel.listBadServers() | |
60862425 | 64 | |
3fd3ab2d C |
65 | const serversRemovePromises = servers.map(server => server.destroy()) |
66 | await Promise.all(serversRemovePromises) | |
60862425 | 67 | |
3fd3ab2d | 68 | const numberOfServersRemoved = servers.length |
60862425 | 69 | |
3fd3ab2d C |
70 | if (numberOfServersRemoved) { |
71 | logger.info('Removed %d servers.', numberOfServersRemoved) | |
72 | } else { | |
73 | logger.info('No need to remove bad servers.') | |
74 | } | |
75 | } catch (err) { | |
76 | logger.error('Cannot remove bad servers.', err) | |
60862425 | 77 | } |
60862425 | 78 | } |
39445ead | 79 | |
3fd3ab2d C |
80 | private static incrementScores (ids: number[], value: number) { |
81 | const update = { | |
82 | score: Sequelize.literal('score +' + value) | |
83 | } | |
39445ead | 84 | |
3fd3ab2d C |
85 | const options = { |
86 | where: { | |
87 | id: { | |
88 | [Sequelize.Op.in]: ids | |
89 | } | |
90 | }, | |
91 | // In this case score is a literal and not an integer so we do not validate it | |
92 | validate: false | |
93 | } | |
39445ead | 94 | |
3fd3ab2d C |
95 | return ServerModel.update(update, options) |
96 | } | |
39445ead | 97 | |
3fd3ab2d C |
98 | private static listBadServers () { |
99 | const query = { | |
100 | where: { | |
101 | score: { | |
102 | [Sequelize.Op.lte]: 0 | |
103 | } | |
39445ead C |
104 | } |
105 | } | |
39445ead | 106 | |
3fd3ab2d C |
107 | return ServerModel.findAll(query) |
108 | } | |
39445ead | 109 | } |