mirror of https://github.com/Chocobozzz/PeerTube
Update follower/following counts
parent
6502c3d43e
commit
32b2b43c06
|
@ -9,7 +9,7 @@ import { isTestInstance, root, sanitizeHost, sanitizeUrl } from '../helpers/core
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
const LAST_MIGRATION_VERSION = 170
|
const LAST_MIGRATION_VERSION = 175
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
import * as Sequelize from 'sequelize'
|
||||||
|
import { ACTOR_FOLLOW_SCORE } from '../index'
|
||||||
|
|
||||||
|
async function up (utils: {
|
||||||
|
transaction: Sequelize.Transaction,
|
||||||
|
queryInterface: Sequelize.QueryInterface,
|
||||||
|
sequelize: Sequelize.Sequelize
|
||||||
|
}): Promise<void> {
|
||||||
|
const query = 'UPDATE "actor" SET ' +
|
||||||
|
'"followersCount" = (SELECT COUNT(*) FROM "actorFollow" WHERE "actor"."id" = "actorFollow"."targetActorId"), ' +
|
||||||
|
'"followingCount" = (SELECT COUNT(*) FROM "actorFollow" WHERE "actor"."id" = "actorFollow"."actorId") ' +
|
||||||
|
'WHERE "actor"."serverId" IS NULL'
|
||||||
|
|
||||||
|
await utils.sequelize.query(query)
|
||||||
|
}
|
||||||
|
|
||||||
|
function down (options) {
|
||||||
|
throw new Error('Not implemented.')
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
up,
|
||||||
|
down
|
||||||
|
}
|
|
@ -314,6 +314,7 @@ async function refreshActorIfNeeded (actor: ActorModel) {
|
||||||
if (result === undefined) throw new Error('Cannot fetch remote actor in refresh actor.')
|
if (result === undefined) throw new Error('Cannot fetch remote actor in refresh actor.')
|
||||||
|
|
||||||
return sequelizeTypescript.transaction(async t => {
|
return sequelizeTypescript.transaction(async t => {
|
||||||
|
logger.info('coucou', result.actor.toJSON())
|
||||||
updateInstanceWithAnother(actor, result.actor)
|
updateInstanceWithAnother(actor, result.actor)
|
||||||
|
|
||||||
if (result.avatarName !== undefined) {
|
if (result.avatarName !== undefined) {
|
||||||
|
|
|
@ -51,6 +51,9 @@ async function follow (actor: ActorModel, targetActorURL: string) {
|
||||||
transaction: t
|
transaction: t
|
||||||
})
|
})
|
||||||
|
|
||||||
|
actorFollow.ActorFollower = actor
|
||||||
|
actorFollow.ActorFollowing = targetActor
|
||||||
|
|
||||||
if (actorFollow.state !== 'accepted') {
|
if (actorFollow.state !== 'accepted') {
|
||||||
actorFollow.state = 'accepted'
|
actorFollow.state = 'accepted'
|
||||||
await actorFollow.save({ transaction: t })
|
await actorFollow.save({ transaction: t })
|
||||||
|
|
|
@ -2,6 +2,7 @@ import * as Bluebird from 'bluebird'
|
||||||
import { values } from 'lodash'
|
import { values } from 'lodash'
|
||||||
import * as Sequelize from 'sequelize'
|
import * as Sequelize from 'sequelize'
|
||||||
import {
|
import {
|
||||||
|
AfterCreate, AfterDestroy, AfterUpdate,
|
||||||
AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, IsInt, Max, Model, Table,
|
AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, IsInt, Max, Model, Table,
|
||||||
UpdatedAt
|
UpdatedAt
|
||||||
} from 'sequelize-typescript'
|
} from 'sequelize-typescript'
|
||||||
|
@ -79,6 +80,25 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
|
||||||
})
|
})
|
||||||
ActorFollowing: ActorModel
|
ActorFollowing: ActorModel
|
||||||
|
|
||||||
|
@AfterCreate
|
||||||
|
@AfterUpdate
|
||||||
|
static incrementFollowerAndFollowingCount (instance: ActorFollowModel) {
|
||||||
|
if (instance.state !== 'accepted') return
|
||||||
|
|
||||||
|
return Promise.all([
|
||||||
|
ActorModel.incrementFollows(instance.actorId, 'followingCount', 1),
|
||||||
|
ActorModel.incrementFollows(instance.targetActorId, 'followersCount', 1)
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterDestroy
|
||||||
|
static decrementFollowerAndFollowingCount (instance: ActorFollowModel) {
|
||||||
|
return Promise.all([
|
||||||
|
ActorModel.incrementFollows(instance.actorId, 'followingCount',-1),
|
||||||
|
ActorModel.incrementFollows(instance.targetActorId, 'followersCount', -1)
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
// Remove actor follows with a score of 0 (too many requests where they were unreachable)
|
// Remove actor follows with a score of 0 (too many requests where they were unreachable)
|
||||||
static async removeBadActorFollows () {
|
static async removeBadActorFollows () {
|
||||||
const actorFollows = await ActorFollowModel.listBadActorFollows()
|
const actorFollows = await ActorFollowModel.listBadActorFollows()
|
||||||
|
|
|
@ -264,6 +264,16 @@ export class ActorModel extends Model<ActorModel> {
|
||||||
return ActorModel.scope(ScopeNames.FULL).findOne(query)
|
return ActorModel.scope(ScopeNames.FULL).findOne(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static incrementFollows (id: number, column: 'followersCount' | 'followingCount', by: number) {
|
||||||
|
// FIXME: typings
|
||||||
|
return (ActorModel as any).increment(column, {
|
||||||
|
by,
|
||||||
|
where: {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
toFormattedJSON () {
|
toFormattedJSON () {
|
||||||
let avatar: Avatar = null
|
let avatar: Avatar = null
|
||||||
if (this.Avatar) {
|
if (this.Avatar) {
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
} from '../../utils/index'
|
} from '../../utils/index'
|
||||||
import { dateIsValid } from '../../utils/miscs/miscs'
|
import { dateIsValid } from '../../utils/miscs/miscs'
|
||||||
import { follow, getFollowersListPaginationAndSort, getFollowingListPaginationAndSort, unfollow } from '../../utils/server/follows'
|
import { follow, getFollowersListPaginationAndSort, getFollowingListPaginationAndSort, unfollow } from '../../utils/server/follows'
|
||||||
|
import { expectAccountFollows } from '../../utils/users/accounts'
|
||||||
import { userLogin } from '../../utils/users/login'
|
import { userLogin } from '../../utils/users/login'
|
||||||
import { createUser } from '../../utils/users/users'
|
import { createUser } from '../../utils/users/users'
|
||||||
import {
|
import {
|
||||||
|
@ -116,6 +117,19 @@ describe('Test follows', function () {
|
||||||
expect(follows.length).to.equal(0)
|
expect(follows.length).to.equal(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should have the correct following counts', async function () {
|
||||||
|
await expectAccountFollows(servers[0].url, 'peertube@localhost:9001', 0, 2)
|
||||||
|
await expectAccountFollows(servers[0].url, 'peertube@localhost:9002', 1, 0)
|
||||||
|
await expectAccountFollows(servers[0].url, 'peertube@localhost:9003', 1, 0)
|
||||||
|
|
||||||
|
// Server 2 and 3 does not know server 1 follow another server (there was not a refresh)
|
||||||
|
await expectAccountFollows(servers[1].url, 'peertube@localhost:9001', 0, 1)
|
||||||
|
await expectAccountFollows(servers[1].url, 'peertube@localhost:9002', 1, 0)
|
||||||
|
|
||||||
|
await expectAccountFollows(servers[2].url, 'peertube@localhost:9001', 0, 1)
|
||||||
|
await expectAccountFollows(servers[2].url, 'peertube@localhost:9003', 1, 0)
|
||||||
|
})
|
||||||
|
|
||||||
it('Should unfollow server 3 on server 1', async function () {
|
it('Should unfollow server 3 on server 1', async function () {
|
||||||
this.timeout(5000)
|
this.timeout(5000)
|
||||||
|
|
||||||
|
@ -144,6 +158,17 @@ describe('Test follows', function () {
|
||||||
expect(follows.length).to.equal(0)
|
expect(follows.length).to.equal(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should have the correct following counts 2', async function () {
|
||||||
|
await expectAccountFollows(servers[0].url, 'peertube@localhost:9001', 0, 1)
|
||||||
|
await expectAccountFollows(servers[0].url, 'peertube@localhost:9002', 1, 0)
|
||||||
|
|
||||||
|
await expectAccountFollows(servers[1].url, 'peertube@localhost:9001', 0, 1)
|
||||||
|
await expectAccountFollows(servers[1].url, 'peertube@localhost:9002', 1, 0)
|
||||||
|
|
||||||
|
await expectAccountFollows(servers[2].url, 'peertube@localhost:9001', 0, 0)
|
||||||
|
await expectAccountFollows(servers[2].url, 'peertube@localhost:9003', 0, 0)
|
||||||
|
})
|
||||||
|
|
||||||
it('Should upload a video on server 2 ans 3 and propagate only the video of server 2', async function () {
|
it('Should upload a video on server 2 ans 3 and propagate only the video of server 2', async function () {
|
||||||
this.timeout(10000)
|
this.timeout(10000)
|
||||||
|
|
||||||
|
@ -223,6 +248,18 @@ describe('Test follows', function () {
|
||||||
await wait(7000)
|
await wait(7000)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should have the correct following counts 2', async function () {
|
||||||
|
await expectAccountFollows(servers[0].url, 'peertube@localhost:9001', 0, 2)
|
||||||
|
await expectAccountFollows(servers[0].url, 'peertube@localhost:9002', 1, 0)
|
||||||
|
await expectAccountFollows(servers[0].url, 'peertube@localhost:9003', 1, 0)
|
||||||
|
|
||||||
|
await expectAccountFollows(servers[1].url, 'peertube@localhost:9001', 0, 1)
|
||||||
|
await expectAccountFollows(servers[1].url, 'peertube@localhost:9002', 1, 0)
|
||||||
|
|
||||||
|
await expectAccountFollows(servers[2].url, 'peertube@localhost:9001', 0, 1)
|
||||||
|
await expectAccountFollows(servers[2].url, 'peertube@localhost:9003', 1, 0)
|
||||||
|
})
|
||||||
|
|
||||||
it('Should propagate videos', async function () {
|
it('Should propagate videos', async function () {
|
||||||
const res = await getVideosList(servers[ 0 ].url)
|
const res = await getVideosList(servers[ 0 ].url)
|
||||||
expect(res.body.total).to.equal(7)
|
expect(res.body.total).to.equal(7)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { expect } from 'chai'
|
||||||
|
import { Account } from '../../../../shared/models/actors'
|
||||||
import { makeGetRequest } from '../requests/requests'
|
import { makeGetRequest } from '../requests/requests'
|
||||||
|
|
||||||
function getAccountsList (url: string, sort = '-createdAt', statusCodeExpected = 200) {
|
function getAccountsList (url: string, sort = '-createdAt', statusCodeExpected = 200) {
|
||||||
|
@ -21,9 +23,19 @@ function getAccount (url: string, accountId: number | string, statusCodeExpected
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function expectAccountFollows (url: string, nameWithDomain: string, followersCount: number, followingCount: number) {
|
||||||
|
const res = await getAccountsList(url)
|
||||||
|
const account = res.body.data.find((a: Account) => a.name + '@' + a.host === nameWithDomain)
|
||||||
|
|
||||||
|
const message = `${nameWithDomain} on ${url}`
|
||||||
|
expect(account.followersCount).to.equal(followersCount, message)
|
||||||
|
expect(account.followingCount).to.equal(followingCount, message)
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
export {
|
export {
|
||||||
getAccount,
|
getAccount,
|
||||||
|
expectAccountFollows,
|
||||||
getAccountsList
|
getAccountsList
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue