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