]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/lib/jobs/activitypub-http-job-scheduler/activitypub-http-job-scheduler.ts
Avoid making retried requests to dead followers
[github/Chocobozzz/PeerTube.git] / server / lib / jobs / activitypub-http-job-scheduler / activitypub-http-job-scheduler.ts
CommitLineData
63c93323 1import { JobCategory } from '../../../../shared'
da854ddd
C
2import { buildSignedActivity } from '../../../helpers/activitypub'
3import { logger } from '../../../helpers/logger'
4import { getServerActor } from '../../../helpers/utils'
3fd3ab2d 5import { ACTIVITY_PUB } from '../../../initializers'
50d6de9c 6import { ActorModel } from '../../../models/activitypub/actor'
6502c3d4 7import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
63c93323 8import { JobHandler, JobScheduler } from '../job-scheduler'
afffe988
C
9
10import * as activitypubHttpBroadcastHandler from './activitypub-http-broadcast-handler'
c986175d 11import * as activitypubHttpFetcherHandler from './activitypub-http-fetcher-handler'
63c93323 12import * as activitypubHttpUnicastHandler from './activitypub-http-unicast-handler'
afffe988
C
13
14type ActivityPubHttpPayload = {
15 uris: string[]
50d6de9c 16 signatureActorId?: number
c986175d 17 body?: any
0032ebe9 18 attemptNumber?: number
afffe988 19}
0032ebe9 20
afffe988
C
21const jobHandlers: { [ handlerName: string ]: JobHandler<ActivityPubHttpPayload, void> } = {
22 activitypubHttpBroadcastHandler,
c986175d
C
23 activitypubHttpUnicastHandler,
24 activitypubHttpFetcherHandler
afffe988
C
25}
26const jobCategory: JobCategory = 'activitypub-http'
27
28const activitypubHttpJobScheduler = new JobScheduler(jobCategory, jobHandlers)
29
60650c77 30async function maybeRetryRequestLater (err: Error, payload: ActivityPubHttpPayload, uri: string) {
0032ebe9
C
31 logger.warn('Cannot make request to %s.', uri, err)
32
33 let attemptNumber = payload.attemptNumber || 1
34 attemptNumber += 1
35
36 if (attemptNumber < ACTIVITY_PUB.MAX_HTTP_ATTEMPT) {
37 logger.debug('Retrying request to %s (attempt %d/%d).', uri, attemptNumber, ACTIVITY_PUB.MAX_HTTP_ATTEMPT, err)
38
6502c3d4
C
39 const actor = await ActorFollowModel.loadByFollowerInbox(uri, undefined)
40 if (!actor) {
41 logger.debug('Actor %s is not a follower, do not retry the request.', uri)
42 return false
43 }
44
0032ebe9
C
45 const newPayload = Object.assign(payload, {
46 uris: [ uri ],
47 attemptNumber
48 })
60650c77
C
49 await activitypubHttpJobScheduler.createJob(undefined, 'activitypubHttpUnicastHandler', newPayload)
50
51 return true
0032ebe9 52 }
60650c77
C
53
54 return false
0032ebe9
C
55}
56
63c93323
C
57async function computeBody (payload: ActivityPubHttpPayload) {
58 let body = payload.body
59
50d6de9c
C
60 if (payload.signatureActorId) {
61 const actorSignature = await ActorModel.load(payload.signatureActorId)
e12a0092 62 if (!actorSignature) throw new Error('Unknown signature actor id.')
50d6de9c 63 body = await buildSignedActivity(actorSignature, payload.body)
63c93323 64 }
df1966c9 65
63c93323
C
66 return body
67}
68
e12a0092
C
69async function buildSignedRequestOptions (payload: ActivityPubHttpPayload) {
70 let actor: ActorModel
71 if (payload.signatureActorId) {
72 actor = await ActorModel.load(payload.signatureActorId)
73 if (!actor) throw new Error('Unknown signature actor id.')
74 } else {
75 // We need to sign the request, so use the server
76 actor = await getServerActor()
77 }
78
79 const keyId = actor.getWebfingerUrl()
80 return {
81 algorithm: 'rsa-sha256',
82 authorizationHeaderName: 'Signature',
83 keyId,
84 key: actor.privateKey
85 }
86}
87
afffe988
C
88export {
89 ActivityPubHttpPayload,
0032ebe9 90 activitypubHttpJobScheduler,
63c93323 91 maybeRetryRequestLater,
e12a0092
C
92 computeBody,
93 buildSignedRequestOptions
afffe988 94}