]> git.mxchange.org Git - friendica.git/commitdiff
Configurable recursion depth when fetching replies
authorMichael <heluecht@pirati.ca>
Wed, 14 Aug 2024 08:16:33 +0000 (08:16 +0000)
committerMichael <heluecht@pirati.ca>
Wed, 14 Aug 2024 08:16:33 +0000 (08:16 +0000)
src/Protocol/ActivityPub/Processor.php
static/defaults.config.php

index 3de1fc7d3c11004aa4fe65989ed04a96be09da4c..2e1d4430f9766005752edae5f95df14e45dff8ed 100644 (file)
@@ -267,6 +267,7 @@ class Processor
                                self::updateEvent($post['event-id'], $activity);
                        }
                }
+               self::processReplies($activity, $item);
        }
 
        /**
@@ -524,28 +525,34 @@ class Processor
                        }
                }
 
-               if (DI::config()->get('system', 'decoupled_receiver') && ($activity['completion-mode'] ?? Receiver::COMPLETION_NONE != Receiver::COMPLETION_REPLIES)) {
-                       $replies = [$item['thr-parent']];
-                       if (!empty($item['parent-uri'])) {
-                               $replies[] = $item['parent-uri'];
-                       }
-                       $condition = DBA::mergeConditions(['uri' => $replies], ["`replies-id` IS NOT NULL"]);
-                       $posts = Post::select(['replies', 'replies-id'], $condition);
-                       while ($post = Post::fetch($posts)) {
-                               $cachekey = 'Processor-CreateItem-Replies-' . $post['replies-id'];
-                               if (!DI::cache()->get($cachekey)) {
-                                       self::fetchReplies($post['replies'], $activity);
-                                       DI::cache()->set($cachekey, true);
-                               }
-                       }
-                       DBA::close($replies);
+               return $item;
+       }
 
-                       if (!empty($item['replies'])) {
-                               self::fetchReplies($item['replies'], $activity);
+       private static function processReplies(array $activity, array $item)
+       {
+               // @todo fetch replies not only in the decoupled mode
+               if (!DI::config()->get('system', 'decoupled_receiver')) {
+                       return;
+               }
+               
+               $replies = [$item['thr-parent']];
+               if (!empty($item['parent-uri'])) {
+                       $replies[] = $item['parent-uri'];
+               }
+               $condition = DBA::mergeConditions(['uri' => $replies], ["`replies-id` IS NOT NULL"]);
+               $posts = Post::select(['replies', 'replies-id'], $condition);
+               while ($post = Post::fetch($posts)) {
+                       $cachekey = 'Processor-CreateItem-Replies-' . $post['replies-id'];
+                       if (!DI::cache()->get($cachekey)) {
+                               self::fetchReplies($post['replies'], $activity);
+                               DI::cache()->set($cachekey, true);
                        }
                }
+               DBA::close($replies);
 
-               return $item;
+               if (!empty($item['replies'])) {
+                       self::fetchReplies($item['replies'], $activity);
+               }
        }
 
        /**
@@ -1247,7 +1254,7 @@ class Processor
                Queue::remove($activity);
 
                if ($success && Queue::hasChildren($item['uri']) && Post::exists(['uri' => $item['uri']])) {
-                       Queue::processReplyByUri($item['uri']);
+                       Queue::processReplyByUri($item['uri'], $activity);
                }
 
                // Store send a follow request for every reshare - but only when the item had been stored
@@ -1259,6 +1266,10 @@ class Processor
                                ActivityPub\Transmitter::sendFollowObject($item['uri'], $item['author-link']);
                        }
                }
+
+               if ($success) {
+                       self::processReplies($activity, $item);
+               }
        }
 
        /**
@@ -1794,10 +1805,27 @@ class Processor
 
        private static function fetchReplies(string $url, array $child)
        {
-               if (in_array(__FUNCTION__, $child['callstack'] ?? [])) {
-                       Logger::notice('Callstack already contains "' . __FUNCTION__ . '"', ['callstack' => $child['callstack']]);
+               $callstack_count = 0;
+               foreach ($child['callstack'] ?? [] as $function) {
+                       if ($function == __FUNCTION__) {
+                               ++$callstack_count;
+                       }
+               }
+
+               $callstack = array_slice(array_column(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), 'function'), 1);
+               $system_count = 0;
+               foreach ($callstack as $function) {
+                       if ($function == __FUNCTION__) {
+                               ++$system_count;
+                       }
+               }
+
+               $maximum_fetchreplies_depth = DI::config()->get('system', 'max_fetchreplies_depth');
+               if (max($callstack_count, $system_count) == $maximum_fetchreplies_depth) {
+                       Logger::notice('Maximum callstack depth reached', ['max' => $maximum_fetchreplies_depth, 'count' => $callstack_count, 'system-count' => $system_count, 'replies' => $url, 'callstack' => $child['callstack'] ?? [], 'system' => $callstack]);
                        return;
                }
+
                $child['callstack'] = self::addToCallstack($child['callstack'] ?? []);
 
                $replies = ActivityPub::fetchItems($url);
@@ -1805,7 +1833,7 @@ class Processor
                        Logger::notice('No replies', ['replies' => $url]);
                        return;
                }
-               Logger::notice('Fetch replies - start', ['replies' => $url]);
+               Logger::notice('Fetch replies - start', ['replies' => $url, 'callstack' => $child['callstack'], 'system' => $callstack]);
                $fetched = 0;
                foreach ($replies as $reply) {
                        if (is_array($reply)) {
index 53922481767bcc090d8d937e8b87127ed40d6886..6bdc9c53b55ce1039f98955cc96010d8efcac7e1 100644 (file)
@@ -388,6 +388,10 @@ return [
                // Maximum number of feed items that are fetched and processed. For unlimited items set to 0.
                'max_feed_items' => 20,
 
+               // max_fetchreplies_depth (Integer)
+               // Maximum number of "fetchreplies" activities in the callstack. The higher, the more complete a thread will be.
+               'max_fetchreplies_depth' => 2,
+
                // max_image_length (Integer)
                // An alternate way of limiting picture upload sizes.
                // Specify the maximum pixel length that pictures are allowed to be (for non-square pictures, it will apply to the longest side).