From 60650c77c8a2a98e92d869b237ae4900f369a8fc Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 11 Jan 2018 09:35:50 +0100 Subject: Add scores to follows and remove bad ones --- server/models/account/account.ts | 1 - server/models/activitypub/actor-follow.ts | 79 +++++++++++++++++++++++++++- server/models/activitypub/actor.ts | 13 ++--- server/models/server/server.ts | 85 +------------------------------ server/models/video/video-channel.ts | 2 +- 5 files changed, 84 insertions(+), 96 deletions(-) (limited to 'server/models') diff --git a/server/models/account/account.ts b/server/models/account/account.ts index 47336d1e0..f81c50180 100644 --- a/server/models/account/account.ts +++ b/server/models/account/account.ts @@ -179,7 +179,6 @@ export class AccountModel extends Model { const actor = this.Actor.toFormattedJSON() const account = { id: this.id, - name: this.Actor.preferredUsername, displayName: this.name, createdAt: this.createdAt, updatedAt: this.updatedAt diff --git a/server/models/activitypub/actor-follow.ts b/server/models/activitypub/actor-follow.ts index 5fcc3449d..78a65a0ff 100644 --- a/server/models/activitypub/actor-follow.ts +++ b/server/models/activitypub/actor-follow.ts @@ -1,8 +1,14 @@ import * as Bluebird from 'bluebird' import { values } from 'lodash' import * as Sequelize from 'sequelize' -import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' +import { + AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, IsInt, Max, Model, Table, + UpdatedAt +} from 'sequelize-typescript' import { FollowState } from '../../../shared/models/actors' +import { AccountFollow } from '../../../shared/models/actors/follow.model' +import { logger } from '../../helpers/logger' +import { ACTOR_FOLLOW_SCORE } from '../../initializers' import { FOLLOW_STATES } from '../../initializers/constants' import { ServerModel } from '../server/server' import { getSort } from '../utils' @@ -20,6 +26,9 @@ import { ActorModel } from './actor' { fields: [ 'actorId', 'targetActorId' ], unique: true + }, + { + fields: [ 'score' ] } ] }) @@ -29,6 +38,13 @@ export class ActorFollowModel extends Model { @Column(DataType.ENUM(values(FOLLOW_STATES))) state: FollowState + @AllowNull(false) + @Default(ACTOR_FOLLOW_SCORE.BASE) + @IsInt + @Max(ACTOR_FOLLOW_SCORE.MAX) + @Column + score: number + @CreatedAt createdAt: Date @@ -63,6 +79,34 @@ export class ActorFollowModel extends Model { }) ActorFollowing: ActorModel + // Remove actor follows with a score of 0 (too many requests where they were unreachable) + static async removeBadActorFollows () { + const actorFollows = await ActorFollowModel.listBadActorFollows() + + const actorFollowsRemovePromises = actorFollows.map(actorFollow => actorFollow.destroy()) + await Promise.all(actorFollowsRemovePromises) + + const numberOfActorFollowsRemoved = actorFollows.length + + if (numberOfActorFollowsRemoved) logger.info('Removed bad %d actor follows.', numberOfActorFollowsRemoved) + } + + static updateActorFollowsScoreAndRemoveBadOnes (goodInboxes: string[], badInboxes: string[], t: Sequelize.Transaction) { + if (goodInboxes.length === 0 && badInboxes.length === 0) return + + logger.info('Updating %d good actor follows and %d bad actor follows scores.', goodInboxes.length, badInboxes.length) + + if (goodInboxes.length !== 0) { + ActorFollowModel.incrementScores(goodInboxes, ACTOR_FOLLOW_SCORE.BONUS, t) + .catch(err => logger.error('Cannot increment scores of good actor follows.', err)) + } + + if (badInboxes.length !== 0) { + ActorFollowModel.incrementScores(badInboxes, ACTOR_FOLLOW_SCORE.PENALTY, t) + .catch(err => logger.error('Cannot decrement scores of bad actor follows.', err)) + } + } + static loadByActorAndTarget (actorId: number, targetActorId: number, t?: Sequelize.Transaction) { const query = { where: { @@ -260,7 +304,37 @@ export class ActorFollowModel extends Model { } } - toFormattedJSON () { + private static incrementScores (inboxUrls: string[], value: number, t: Sequelize.Transaction) { + const inboxUrlsString = inboxUrls.map(url => `'${url}'`).join(',') + + const query = 'UPDATE "actorFollow" SET "score" = "score" +' + value + ' ' + + 'WHERE id IN (' + + 'SELECT "actorFollow"."id" FROM "actorFollow" ' + + 'INNER JOIN "actor" ON "actor"."id" = "actorFollow"."actorId" ' + + 'WHERE "actor"."inboxUrl" IN (' + inboxUrlsString + ') OR "actor"."sharedInboxUrl" IN (' + inboxUrlsString + ')' + + ')' + + const options = { + type: Sequelize.QueryTypes.BULKUPDATE, + transaction: t + } + + return ActorFollowModel.sequelize.query(query, options) + } + + private static listBadActorFollows () { + const query = { + where: { + score: { + [Sequelize.Op.lte]: 0 + } + } + } + + return ActorFollowModel.findAll(query) + } + + toFormattedJSON (): AccountFollow { const follower = this.ActorFollower.toFormattedJSON() const following = this.ActorFollowing.toFormattedJSON() @@ -268,6 +342,7 @@ export class ActorFollowModel extends Model { id: this.id, follower, following, + score: this.score, state: this.state, createdAt: this.createdAt, updatedAt: this.updatedAt diff --git a/server/models/activitypub/actor.ts b/server/models/activitypub/actor.ts index b88e06b41..912d8d748 100644 --- a/server/models/activitypub/actor.ts +++ b/server/models/activitypub/actor.ts @@ -204,7 +204,7 @@ export class ActorModel extends Model { VideoChannel: VideoChannelModel static load (id: number) { - return ActorModel.scope(ScopeNames.FULL).findById(id) + return ActorModel.unscoped().findById(id) } static listByFollowersUrls (followersUrls: string[], transaction?: Sequelize.Transaction) { @@ -267,20 +267,17 @@ export class ActorModel extends Model { avatar = this.Avatar.toFormattedJSON() } - let score: number - if (this.Server) { - score = this.Server.score - } - return { id: this.id, url: this.url, uuid: this.uuid, + name: this.preferredUsername, host: this.getHost(), - score, followingCount: this.followingCount, followersCount: this.followersCount, - avatar + avatar, + createdAt: this.createdAt, + updatedAt: this.updatedAt } } diff --git a/server/models/server/server.ts b/server/models/server/server.ts index d35aa0ca4..c43146156 100644 --- a/server/models/server/server.ts +++ b/server/models/server/server.ts @@ -1,8 +1,5 @@ -import * as Sequelize from 'sequelize' -import { AllowNull, Column, CreatedAt, Default, Is, IsInt, Max, Model, Table, UpdatedAt } from 'sequelize-typescript' +import { AllowNull, Column, CreatedAt, Is, 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({ @@ -11,9 +8,6 @@ import { throwIfNotValid } from '../utils' { fields: [ 'host' ], unique: true - }, - { - fields: [ 'score' ] } ] }) @@ -24,86 +18,9 @@ export class ServerModel extends Model { @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) - } } diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts index acc2486b3..e2cbf0422 100644 --- a/server/models/video/video-channel.ts +++ b/server/models/video/video-channel.ts @@ -228,7 +228,7 @@ export class VideoChannelModel extends Model { const actor = this.Actor.toFormattedJSON() const account = { id: this.id, - name: this.name, + displayName: this.name, description: this.description, isLocal: this.Actor.isOwned(), createdAt: this.createdAt, -- cgit v1.2.3