Try to fix subscriptions inconsistencies

This commit is contained in:
Chocobozzz 2020-01-08 15:11:38 +01:00
parent 440d39c52d
commit e612209767
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
12 changed files with 37 additions and 28 deletions

View File

@ -25,7 +25,7 @@
</div> </div>
</div> </div>
<div class="no-results" i18n *ngIf="pagination.totalItems === 0">No results.</div> <div class="no-results" i18n *ngIf="hasDoneFirstQuery && videos.length === 0">No results.</div>
<div <div
myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true" [dataObservable]="onDataSubject.asObservable()" myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true" [dataObservable]="onDataSubject.asObservable()"
class="videos" class="videos"

View File

@ -35,7 +35,7 @@ async function sendUpdateVideo (videoArg: MVideoAPWithoutCaption, t: Transaction
// Needed to build the AP object // Needed to build the AP object
if (!video.VideoCaptions) { if (!video.VideoCaptions) {
video.VideoCaptions = await video.$get('VideoCaptions', { transaction: t }) as VideoCaptionModel[] video.VideoCaptions = await video.$get('VideoCaptions', { transaction: t })
} }
const videoObject = video.toActivityPubObject() const videoObject = video.toActivityPubObject()

View File

@ -86,7 +86,7 @@ async function federateVideoIfNeeded (videoArg: MVideoAPWithoutCaption, isNewVid
video.VideoCaptions = await video.$get('VideoCaptions', { video.VideoCaptions = await video.$get('VideoCaptions', {
attributes: [ 'language' ], attributes: [ 'language' ],
transaction transaction
}) as VideoCaptionModel[] })
} }
if (isNewVideo) { if (isNewVideo) {

View File

@ -206,7 +206,7 @@ async function generateHlsPlaylist (video: MVideoWithFile, resolution: VideoReso
await createTorrentAndSetInfoHash(videoStreamingPlaylist, newVideoFile) await createTorrentAndSetInfoHash(videoStreamingPlaylist, newVideoFile)
await newVideoFile.save() await newVideoFile.save()
videoStreamingPlaylist.VideoFiles = await videoStreamingPlaylist.$get('VideoFiles') as VideoFileModel[] videoStreamingPlaylist.VideoFiles = await videoStreamingPlaylist.$get('VideoFiles')
video.setHLSPlaylist(videoStreamingPlaylist) video.setHLSPlaylist(videoStreamingPlaylist)

View File

@ -223,7 +223,7 @@ export class AccountModel extends Model<AccountModel> {
@BeforeDestroy @BeforeDestroy
static async sendDeleteIfOwned (instance: AccountModel, options) { static async sendDeleteIfOwned (instance: AccountModel, options) {
if (!instance.Actor) { if (!instance.Actor) {
instance.Actor = await instance.$get('Actor', { transaction: options.transaction }) as ActorModel instance.Actor = await instance.$get('Actor', { transaction: options.transaction })
} }
await ActorFollowModel.removeFollowsOf(instance.Actor.id, options.transaction) await ActorFollowModel.removeFollowsOf(instance.Actor.id, options.transaction)

View File

@ -36,6 +36,7 @@ import {
MActorFollowSubscriptions MActorFollowSubscriptions
} from '@server/typings/models' } from '@server/typings/models'
import { ActivityPubActorType } from '@shared/models' import { ActivityPubActorType } from '@shared/models'
import { afterCommitIfTransaction } from '@server/helpers/database-utils'
@Table({ @Table({
tableName: 'actorFollow', tableName: 'actorFollow',
@ -104,20 +105,20 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
@AfterCreate @AfterCreate
@AfterUpdate @AfterUpdate
static incrementFollowerAndFollowingCount (instance: ActorFollowModel) { static incrementFollowerAndFollowingCount (instance: ActorFollowModel, options: any) {
if (instance.state !== 'accepted') return undefined if (instance.state !== 'accepted') return undefined
return Promise.all([ return Promise.all([
ActorModel.incrementFollows(instance.actorId, 'followingCount', 1), ActorModel.rebuildFollowsCount(instance.actorId, 'following', options.transaction),
ActorModel.incrementFollows(instance.targetActorId, 'followersCount', 1) ActorModel.rebuildFollowsCount(instance.targetActorId, 'followers', options.transaction)
]) ])
} }
@AfterDestroy @AfterDestroy
static decrementFollowerAndFollowingCount (instance: ActorFollowModel) { static decrementFollowerAndFollowingCount (instance: ActorFollowModel, options: any) {
return Promise.all([ return Promise.all([
ActorModel.incrementFollows(instance.actorId, 'followingCount',-1), ActorModel.rebuildFollowsCount(instance.actorId, 'following', options.transaction),
ActorModel.incrementFollows(instance.targetActorId, 'followersCount', -1) ActorModel.rebuildFollowsCount(instance.targetActorId, 'followers', options.transaction)
]) ])
} }

View File

@ -47,7 +47,7 @@ import {
MActorWithInboxes MActorWithInboxes
} from '../../typings/models' } from '../../typings/models'
import * as Bluebird from 'bluebird' import * as Bluebird from 'bluebird'
import { Op, Transaction } from 'sequelize' import { Op, Transaction, literal } from 'sequelize'
enum ScopeNames { enum ScopeNames {
FULL = 'FULL' FULL = 'FULL'
@ -421,13 +421,24 @@ 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) { static rebuildFollowsCount (ofId: number, type: 'followers' | 'following', transaction?: Transaction) {
return ActorModel.increment(column, { const sanitizedOfId = parseInt(ofId + '', 10)
by, const where = { id: sanitizedOfId }
where: {
id let columnToUpdate: string
let columnOfCount: string
if (type === 'followers') {
columnToUpdate = 'followersCount'
columnOfCount = 'targetActorId'
} else {
columnToUpdate = 'followingCount'
columnOfCount = 'actorId'
} }
})
return ActorModel.update({
[columnToUpdate]: literal(`(SELECT COUNT(*) FROM "actorFollow" WHERE "${columnOfCount}" = ${sanitizedOfId})`)
}, { where, transaction })
} }
getSharedInbox (this: MActorWithInboxes) { getSharedInbox (this: MActorWithInboxes) {

View File

@ -79,7 +79,7 @@ export class VideoCaptionModel extends Model<VideoCaptionModel> {
@BeforeDestroy @BeforeDestroy
static async removeFiles (instance: VideoCaptionModel) { static async removeFiles (instance: VideoCaptionModel) {
if (!instance.Video) { if (!instance.Video) {
instance.Video = await instance.$get('Video') as VideoModel instance.Video = await instance.$get('Video')
} }
if (instance.isOwned()) { if (instance.isOwned()) {

View File

@ -249,7 +249,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
@BeforeDestroy @BeforeDestroy
static async sendDeleteIfOwned (instance: VideoChannelModel, options) { static async sendDeleteIfOwned (instance: VideoChannelModel, options) {
if (!instance.Actor) { if (!instance.Actor) {
instance.Actor = await instance.$get('Actor', { transaction: options.transaction }) as ActorModel instance.Actor = await instance.$get('Actor', { transaction: options.transaction })
} }
if (instance.Actor.isOwned()) { if (instance.Actor.isOwned()) {

View File

@ -1061,7 +1061,7 @@ export class VideoModel extends Model<VideoModel> {
if (instance.isOwned()) { if (instance.isOwned()) {
if (!Array.isArray(instance.VideoFiles)) { if (!Array.isArray(instance.VideoFiles)) {
instance.VideoFiles = await instance.$get('VideoFiles') as VideoFileModel[] instance.VideoFiles = await instance.$get('VideoFiles')
} }
// Remove physical files and torrents // Remove physical files and torrents

View File

@ -76,7 +76,6 @@ describe('Test activity pub helpers', function () {
const mastodonObject = cloneDeep(require('./json/mastodon/bad-http-signature.json')) const mastodonObject = cloneDeep(require('./json/mastodon/bad-http-signature.json'))
req.body = mastodonObject.body req.body = mastodonObject.body
req.headers = mastodonObject.headers req.headers = mastodonObject.headers
req.headers.signature = 'Signature ' + req.headers.signature
const parsed = parseHTTPSignature(req, 3600 * 1000 * 365 * 10) const parsed = parseHTTPSignature(req, 3600 * 1000 * 365 * 10)
const publicKey = require('./json/mastodon/public-key.json').publicKey const publicKey = require('./json/mastodon/public-key.json').publicKey
@ -95,7 +94,6 @@ describe('Test activity pub helpers', function () {
const mastodonObject = cloneDeep(require('./json/mastodon/http-signature.json')) const mastodonObject = cloneDeep(require('./json/mastodon/http-signature.json'))
req.body = mastodonObject.body req.body = mastodonObject.body
req.headers = mastodonObject.headers req.headers = mastodonObject.headers
req.headers.signature = 'Signature ' + req.headers.signature
const parsed = parseHTTPSignature(req, 3600 * 1000 * 365 * 10) const parsed = parseHTTPSignature(req, 3600 * 1000 * 365 * 10)
const publicKey = require('./json/mastodon/bad-public-key.json').publicKey const publicKey = require('./json/mastodon/bad-public-key.json').publicKey
@ -114,7 +112,6 @@ describe('Test activity pub helpers', function () {
const mastodonObject = cloneDeep(require('./json/mastodon/http-signature.json')) const mastodonObject = cloneDeep(require('./json/mastodon/http-signature.json'))
req.body = mastodonObject.body req.body = mastodonObject.body
req.headers = mastodonObject.headers req.headers = mastodonObject.headers
req.headers.signature = 'Signature ' + req.headers.signature
let errored = false let errored = false
try { try {
@ -126,7 +123,7 @@ describe('Test activity pub helpers', function () {
expect(errored).to.be.true expect(errored).to.be.true
}) })
it('Should fail without scheme', async function () { it('Should with a scheme', async function () {
const req = buildRequestStub() const req = buildRequestStub()
req.method = 'POST' req.method = 'POST'
req.url = '/accounts/ronan/inbox' req.url = '/accounts/ronan/inbox'
@ -134,6 +131,7 @@ describe('Test activity pub helpers', function () {
const mastodonObject = cloneDeep(require('./json/mastodon/http-signature.json')) const mastodonObject = cloneDeep(require('./json/mastodon/http-signature.json'))
req.body = mastodonObject.body req.body = mastodonObject.body
req.headers = mastodonObject.headers req.headers = mastodonObject.headers
req.headers = 'Signature ' + mastodonObject.headers
let errored = false let errored = false
try { try {
@ -153,7 +151,6 @@ describe('Test activity pub helpers', function () {
const mastodonObject = cloneDeep(require('./json/mastodon/http-signature.json')) const mastodonObject = cloneDeep(require('./json/mastodon/http-signature.json'))
req.body = mastodonObject.body req.body = mastodonObject.body
req.headers = mastodonObject.headers req.headers = mastodonObject.headers
req.headers.signature = 'Signature ' + req.headers.signature
const parsed = parseHTTPSignature(req, 3600 * 1000 * 365 * 10) const parsed = parseHTTPSignature(req, 3600 * 1000 * 365 * 10)
const publicKey = require('./json/mastodon/public-key.json').publicKey const publicKey = require('./json/mastodon/public-key.json').publicKey

View File

@ -419,7 +419,7 @@ describe('Test follows', function () {
await expectAccountFollows(servers[1].url, 'peertube@localhost:' + servers[0].port, 0, 1) await expectAccountFollows(servers[1].url, 'peertube@localhost:' + servers[0].port, 0, 1)
await expectAccountFollows(servers[1].url, 'peertube@localhost:' + servers[1].port, 1, 0) await expectAccountFollows(servers[1].url, 'peertube@localhost:' + servers[1].port, 1, 0)
await expectAccountFollows(servers[2].url, 'peertube@localhost:' + servers[0].port, 0, 2) await expectAccountFollows(servers[2].url, 'peertube@localhost:' + servers[0].port, 0, 1)
await expectAccountFollows(servers[2].url, 'peertube@localhost:' + servers[2].port, 1, 0) await expectAccountFollows(servers[2].url, 'peertube@localhost:' + servers[2].port, 1, 0)
}) })