]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/models/server/server.ts
First step upload with new design
[github/Chocobozzz/PeerTube.git] / server / models / server / server.ts
1 import * as Sequelize from 'sequelize'
2 import { isHostValid, logger } from '../../helpers'
3 import { SERVERS_SCORE } from '../../initializers'
4 import { addMethodsToModel } from '../utils'
5 import { ServerAttributes, ServerInstance, ServerMethods } from './server-interface'
6
7 let Server: Sequelize.Model<ServerInstance, ServerAttributes>
8 let updateServersScoreAndRemoveBadOnes: ServerMethods.UpdateServersScoreAndRemoveBadOnes
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: SERVERS_SCORE.BASE,
26 allowNull: false,
27 validate: {
28 isInt: true,
29 max: SERVERS_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 = [
47 updateServersScoreAndRemoveBadOnes
48 ]
49 addMethodsToModel(Server, classMethods)
50
51 return Server
52 }
53
54 // ------------------------------ Statics ------------------------------
55
56 updateServersScoreAndRemoveBadOnes = function (goodServers: number[], badServers: number[]) {
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 }
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 }