PeerTube_original/server/models/server/server.ts
2017-12-28 11:16:08 +01:00

110 lines
2.8 KiB
TypeScript

import * as Sequelize from 'sequelize'
import { AllowNull, Column, CreatedAt, Default, Is, IsInt, Max, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { isHostValid } from '../../helpers/custom-validators/servers'
import { logger } from '../../helpers/logger'
import { SERVERS_SCORE } from '../../initializers'
import { throwIfNotValid } from '../utils'
@Table({
tableName: 'server',
indexes: [
{
fields: [ 'host' ],
unique: true
},
{
fields: [ 'score' ]
}
]
})
export class ServerModel extends Model<ServerModel> {
@AllowNull(false)
@Is('Host', value => throwIfNotValid(value, isHostValid, 'valid host'))
@Column
host: string
@AllowNull(false)
@Default(SERVERS_SCORE.BASE)
@IsInt
@Max(SERVERS_SCORE.MAX)
@Column
score: number
@CreatedAt
createdAt: Date
@UpdatedAt
updatedAt: Date
static updateServersScoreAndRemoveBadOnes (goodServers: number[], badServers: number[]) {
logger.info('Updating %d good servers and %d bad servers scores.', goodServers.length, badServers.length)
if (goodServers.length !== 0) {
ServerModel.incrementScores(goodServers, SERVERS_SCORE.BONUS)
.catch(err => {
logger.error('Cannot increment scores of good servers.', err)
})
}
if (badServers.length !== 0) {
ServerModel.incrementScores(badServers, SERVERS_SCORE.PENALTY)
.then(() => ServerModel.removeBadServers())
.catch(err => {
if (err) logger.error('Cannot decrement scores of bad servers.', err)
})
}
}
// Remove servers with a score of 0 (too many requests where they were unreachable)
private static async removeBadServers () {
try {
const servers = await ServerModel.listBadServers()
const serversRemovePromises = servers.map(server => server.destroy())
await Promise.all(serversRemovePromises)
const numberOfServersRemoved = servers.length
if (numberOfServersRemoved) {
logger.info('Removed %d servers.', numberOfServersRemoved)
} else {
logger.info('No need to remove bad servers.')
}
} catch (err) {
logger.error('Cannot remove bad servers.', err)
}
}
private static incrementScores (ids: number[], value: number) {
const update = {
score: Sequelize.literal('score +' + value)
}
const options = {
where: {
id: {
[Sequelize.Op.in]: ids
}
},
// In this case score is a literal and not an integer so we do not validate it
validate: false
}
return ServerModel.update(update, options)
}
private static listBadServers () {
const query = {
where: {
score: {
[Sequelize.Op.lte]: 0
}
}
}
return ServerModel.findAll(query)
}
}