]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/lib/activitypub/actors/updater.ts
Try to speed up AP update transaction
[github/Chocobozzz/PeerTube.git] / server / lib / activitypub / actors / updater.ts
CommitLineData
28dfb44b 1import { resetSequelizeInstance, runInReadCommittedTransaction } from '@server/helpers/database-utils'
136d7efd 2import { logger } from '@server/helpers/logger'
136d7efd
C
3import { VideoChannelModel } from '@server/models/video/video-channel'
4import { MAccount, MActor, MActorFull, MChannel } from '@server/types/models'
5import { ActivityPubActor, ActorImageType } from '@shared/models'
6import { updateActorImageInstance } from './image'
7import { fetchActorFollowsCount } from './shared'
8import { getImageInfoFromObject } from './shared/object-to-model-attributes'
9
10export class APActorUpdater {
11
12 private accountOrChannel: MAccount | MChannel
13
14 private readonly actorFieldsSave: object
15 private readonly accountOrChannelFieldsSave: object
16
17 constructor (
18 private readonly actorObject: ActivityPubActor,
19 private readonly actor: MActorFull
20 ) {
21 this.actorFieldsSave = this.actor.toJSON()
22
23 if (this.actorObject.type === 'Group') this.accountOrChannel = this.actor.VideoChannel
24 else this.accountOrChannel = this.actor.Account
25
26 this.accountOrChannelFieldsSave = this.accountOrChannel.toJSON()
27 }
28
29 async update () {
30 const avatarInfo = getImageInfoFromObject(this.actorObject, ActorImageType.AVATAR)
31 const bannerInfo = getImageInfoFromObject(this.actorObject, ActorImageType.BANNER)
32
33 try {
28dfb44b 34 await this.updateActorInstance(this.actor, this.actorObject)
136d7efd 35
28dfb44b
C
36 this.accountOrChannel.name = this.actorObject.name || this.actorObject.preferredUsername
37 this.accountOrChannel.description = this.actorObject.summary
136d7efd 38
28dfb44b 39 if (this.accountOrChannel instanceof VideoChannelModel) this.accountOrChannel.support = this.actorObject.support
136d7efd 40
28dfb44b
C
41 await runInReadCommittedTransaction(async t => {
42 await this.actor.save({ transaction: t })
136d7efd
C
43 await this.accountOrChannel.save({ transaction: t })
44 })
45
28dfb44b
C
46 await runInReadCommittedTransaction(async t => {
47 await updateActorImageInstance(this.actor, ActorImageType.AVATAR, avatarInfo, t)
48 await updateActorImageInstance(this.actor, ActorImageType.BANNER, bannerInfo, t)
49 })
50
136d7efd
C
51 logger.info('Remote account %s updated', this.actorObject.url)
52 } catch (err) {
53 if (this.actor !== undefined && this.actorFieldsSave !== undefined) {
54 resetSequelizeInstance(this.actor, this.actorFieldsSave)
55 }
56
57 if (this.accountOrChannel !== undefined && this.accountOrChannelFieldsSave !== undefined) {
58 resetSequelizeInstance(this.accountOrChannel, this.accountOrChannelFieldsSave)
59 }
60
61 // This is just a debug because we will retry the insert
62 logger.debug('Cannot update the remote account.', { err })
63 throw err
64 }
65 }
66
67 private async updateActorInstance (actorInstance: MActor, actorObject: ActivityPubActor) {
68 const { followersCount, followingCount } = await fetchActorFollowsCount(actorObject)
69
70 actorInstance.type = actorObject.type
71 actorInstance.preferredUsername = actorObject.preferredUsername
72 actorInstance.url = actorObject.id
73 actorInstance.publicKey = actorObject.publicKey.publicKeyPem
74 actorInstance.followersCount = followersCount
75 actorInstance.followingCount = followingCount
76 actorInstance.inboxUrl = actorObject.inbox
77 actorInstance.outboxUrl = actorObject.outbox
78 actorInstance.followersUrl = actorObject.followers
79 actorInstance.followingUrl = actorObject.following
80
81 if (actorObject.published) actorInstance.remoteCreatedAt = new Date(actorObject.published)
82
83 if (actorObject.endpoints?.sharedInbox) {
84 actorInstance.sharedInboxUrl = actorObject.endpoints.sharedInbox
85 }
86
87 // Force actor update
88 actorInstance.changed('updatedAt', true)
89 }
90}