Avoid making retried requests to dead followers
authorChocobozzz <me@florianbigard.com>
Fri, 12 Jan 2018 09:02:11 +0000 (10:02 +0100)
committerChocobozzz <me@florianbigard.com>
Fri, 12 Jan 2018 09:02:11 +0000 (10:02 +0100)
server/lib/activitypub/video-comments.ts
server/lib/jobs/activitypub-http-job-scheduler/activitypub-http-job-scheduler.ts
server/lib/jobs/activitypub-http-job-scheduler/activitypub-http-unicast-handler.ts
server/middlewares/activitypub.ts
server/models/activitypub/actor-follow.ts
server/models/activitypub/actor.ts
server/tests/api/server/handle-down.ts

index 17c86a38144aaa371d17228b091e974fe9c30cf3..b33ae27b19ddcc7a4d51b2bcd5a6c45543d5671d 100644 (file)
@@ -81,7 +81,6 @@ async function resolveThread (url: string, comments: VideoCommentModel[] = []) {
     // Speed up things and resolve directly the thread
     if (commentFromDatabase.InReplyToVideoComment) {
       const data = await VideoCommentModel.listThreadParentComments(commentFromDatabase, undefined, 'DESC')
-      console.log(data)
 
       parentComments = parentComments.concat(data)
     }
index 10423a7df52b828ac98bdf659113a62b1b200504..4459152dbbfb7992f2be99652194cf185cc1fb65 100644 (file)
@@ -4,6 +4,7 @@ import { logger } from '../../../helpers/logger'
 import { getServerActor } from '../../../helpers/utils'
 import { ACTIVITY_PUB } from '../../../initializers'
 import { ActorModel } from '../../../models/activitypub/actor'
+import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
 import { JobHandler, JobScheduler } from '../job-scheduler'
 
 import * as activitypubHttpBroadcastHandler from './activitypub-http-broadcast-handler'
@@ -35,6 +36,12 @@ async function maybeRetryRequestLater (err: Error, payload: ActivityPubHttpPaylo
   if (attemptNumber < ACTIVITY_PUB.MAX_HTTP_ATTEMPT) {
     logger.debug('Retrying request to %s (attempt %d/%d).', uri, attemptNumber, ACTIVITY_PUB.MAX_HTTP_ATTEMPT, err)
 
+    const actor = await ActorFollowModel.loadByFollowerInbox(uri, undefined)
+    if (!actor) {
+      logger.debug('Actor %s is not a follower, do not retry the request.', uri)
+      return false
+    }
+
     const newPayload = Object.assign(payload, {
       uris: [ uri ],
       attemptNumber
index deedf8402aad1dfcf644dc3284cd9acb4db60685..54a7504e84fc8e8a36d919e0e37f19d41fe9b3a8 100644 (file)
@@ -6,10 +6,11 @@ import { ActivityPubHttpPayload, buildSignedRequestOptions, computeBody, maybeRe
 async function process (payload: ActivityPubHttpPayload, jobId: number) {
   logger.info('Processing ActivityPub unicast in job %d.', jobId)
 
+  const uri = payload.uris[0]
+
   const body = await computeBody(payload)
   const httpSignatureOptions = await buildSignedRequestOptions(payload)
 
-  const uri = payload.uris[0]
   const options = {
     method: 'POST',
     uri,
index c7102b6bf7782733330c1c7e29aada3b85bfb5ce..1488b42ab1164bd701db841182da7d92c7eb0613 100644 (file)
@@ -35,7 +35,6 @@ async function checkSignature (req: Request, res: Response, next: NextFunction)
 function executeIfActivityPub (fun: RequestHandler | RequestHandler[]) {
   return (req: Request, res: Response, next: NextFunction) => {
     const accepted = req.accepts(ACCEPT_HEADERS)
-    console.log(accepted)
     if (accepted === false || ACTIVITY_PUB.POTENTIAL_ACCEPT_HEADERS.indexOf(accepted) === -1) {
       return next()
     }
index 920c83d885bc957fa55f40affc970e59746f995b..de5bb6f7440633c0d924d300ed41dc6d4070be6f 100644 (file)
@@ -163,6 +163,34 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
     return ActorFollowModel.findOne(query)
   }
 
+  static loadByFollowerInbox (url: string, t?: Sequelize.Transaction) {
+    const query = {
+      where: {
+        state: 'accepted'
+      },
+      include: [
+        {
+          model: ActorModel,
+          required: true,
+          as: 'ActorFollower',
+          where: {
+            [Sequelize.Op.or]: [
+              {
+                inboxUrl: url
+              },
+              {
+                sharedInboxUrl: url
+              }
+            ]
+          }
+        }
+      ],
+      transaction: t
+    } as any // FIXME: typings does not work
+
+    return ActorFollowModel.findOne(query)
+  }
+
   static listFollowingForApi (id: number, start: number, count: number, sort: string) {
     const query = {
       distinct: true,
index 6c74aa61b38ec295bccb7c4482a2d3185c55db06..17f69f7a7aaa157caef66c60695211be230d0f48 100644 (file)
@@ -68,6 +68,9 @@ enum ScopeNames {
     {
       fields: [ 'preferredUsername', 'serverId' ],
       unique: true
+    },
+    {
+      fields: [ 'inboxUrl', 'sharedInboxUrl' ]
     }
   ]
 })
index cc1ff9a9fd799ffe4926a83a71cd222b8d4340cd..6ca8cfb648dcc80718f576b5b9f3b937dc9dfc7b 100644 (file)
@@ -113,6 +113,10 @@ describe('Test handle downs', function () {
       videos.push(resVideo.body.video)
     }
 
+    await wait(2000)
+
+    await uploadVideo(servers[ 0 ].url, servers[ 0 ].accessToken, videoAttributes)
+
     // Add comments to video 2
     {
       const text = 'thread 1'