Try to fix subscriptions inconsistencies
This commit is contained in:
parent
440d39c52d
commit
e612209767
|
@ -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"
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue