Merge pull request #12557 from annando/reduce-update-contacts

Reduce the amount of "UpdateContact" worker calls
This commit is contained in:
Hypolite Petovan 2022-12-28 13:12:30 -05:00 committed by GitHub
commit 689b6b015b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 89 additions and 17 deletions

View file

@ -329,7 +329,7 @@ class Contact
// Add internal fields // Add internal fields
$removal = []; $removal = [];
if (!empty($fields)) { if (!empty($fields)) {
foreach (['id', 'next-update', 'network'] as $internal) { foreach (['id', 'next-update', 'network', 'local-data'] as $internal) {
if (!in_array($internal, $fields)) { if (!in_array($internal, $fields)) {
$fields[] = $internal; $fields[] = $internal;
$removal[] = $internal; $removal[] = $internal;
@ -358,8 +358,10 @@ class Contact
return []; return [];
} }
$background_update = DI::config()->get('system', 'update_active_contacts') ? $contact['local-data'] : true;
// Update the contact in the background if needed // Update the contact in the background if needed
if (Probe::isProbable($contact['network']) && ($contact['next-update'] < DateTimeFormat::utcNow())) { if ($background_update && !self::isLocal($url) && Probe::isProbable($contact['network']) && ($contact['next-update'] < DateTimeFormat::utcNow())) {
Worker::add(['priority' => Worker::PRIORITY_LOW, 'dont_fork' => true], 'UpdateContact', $contact['id']); Worker::add(['priority' => Worker::PRIORITY_LOW, 'dont_fork' => true], 'UpdateContact', $contact['id']);
} }
@ -1266,12 +1268,14 @@ class Contact
return 0; return 0;
} }
$contact = self::getByURL($url, false, ['id', 'network', 'uri-id', 'next-update'], $uid); $contact = self::getByURL($url, false, ['id', 'network', 'uri-id', 'next-update', 'local-data'], $uid);
if (!empty($contact)) { if (!empty($contact)) {
$contact_id = $contact['id']; $contact_id = $contact['id'];
if (Probe::isProbable($contact['network']) && ($contact['next-update'] < DateTimeFormat::utcNow())) { $background_update = DI::config()->get('system', 'update_active_contacts') ? $contact['local-data'] : true;
if ($background_update && !self::isLocal($url) && Probe::isProbable($contact['network']) && ($contact['next-update'] < DateTimeFormat::utcNow())) {
Worker::add(['priority' => Worker::PRIORITY_LOW, 'dont_fork' => true], 'UpdateContact', $contact['id']); Worker::add(['priority' => Worker::PRIORITY_LOW, 'dont_fork' => true], 'UpdateContact', $contact['id']);
} }
@ -2481,6 +2485,44 @@ class Contact
return true; return true;
} }
/**
* Perform a contact update if the contact is outdated
*
* @param integer $id contact id
* @return bool
*/
public static function updateByIdIfNeeded(int $id): bool
{
$contact = self::selectFirst(['url'], ["`id` = ? AND `next-update` < ?", $id, DateTimeFormat::utcNow()]);
if (empty($contact['url'])) {
return false;
}
if (self::isLocal($contact['url'])) {
return true;
}
$stamp = (float)microtime(true);
self::updateFromProbe($id);
Logger::debug('Contact data is updated.', ['duration' => round((float)microtime(true) - $stamp, 3), 'id' => $id, 'url' => $contact['url'], 'callstack' => System::callstack(20)]);
return true;
}
/**
* Perform a contact update if the contact is outdated
*
* @param string $url contact url
* @return bool
*/
public static function updateByUrlIfNeeded(string $url): bool
{
$id = self::getIdForURL($url, 0, false);
if (!empty($id)) {
return self::updateByIdIfNeeded($id);
}
return (bool)self::getIdForURL($url);
}
/** /**
* Updates contact record by provided id and optional network * Updates contact record by provided id and optional network
* *

View file

@ -206,8 +206,14 @@ class Delivery
private static function setSuccess(array $receivers, bool $success) private static function setSuccess(array $receivers, bool $success)
{ {
$gsid = null; $gsid = null;
$update_counter = 0;
foreach ($receivers as $receiver) { foreach ($receivers as $receiver) {
// Only update the first 10 receivers to avoid flooding the remote system with requests
if ($success && ($update_counter < 10) && Contact::updateByIdIfNeeded($receiver)) {
$update_counter++;
}
$contact = Contact::getById($receiver); $contact = Contact::getById($receiver);
if (empty($contact)) { if (empty($contact)) {
continue; continue;

View file

@ -1530,6 +1530,12 @@ class Processor
$ldactivity['recursion-depth'] = !empty($child['recursion-depth']) ? $child['recursion-depth'] + 1 : 0; $ldactivity['recursion-depth'] = !empty($child['recursion-depth']) ? $child['recursion-depth'] + 1 : 0;
if ($object_actor != $actor) {
Contact::updateByUrlIfNeeded($object_actor);
}
Contact::updateByUrlIfNeeded($actor);
if (!empty($relay_actor)) { if (!empty($relay_actor)) {
$ldactivity['thread-completion'] = $ldactivity['from-relay'] = Contact::getIdForURL($relay_actor); $ldactivity['thread-completion'] = $ldactivity['from-relay'] = Contact::getIdForURL($relay_actor);
$ldactivity['completion-mode'] = Receiver::COMPLETION_RELAY; $ldactivity['completion-mode'] = Receiver::COMPLETION_RELAY;

View file

@ -315,11 +315,14 @@ class Receiver
$object_type = JsonLD::fetchElement($activity['as:object'], '@type'); $object_type = JsonLD::fetchElement($activity['as:object'], '@type');
} }
$fetched = false;
if (!empty($id) && !$trust_source) { if (!empty($id) && !$trust_source) {
$fetch_uid = $uid ?: self::getBestUserForActivity($activity); $fetch_uid = $uid ?: self::getBestUserForActivity($activity);
$fetched_activity = Processor::fetchCachedActivity($fetch_id, $fetch_uid); $fetched_activity = Processor::fetchCachedActivity($fetch_id, $fetch_uid);
if (!empty($fetched_activity)) { if (!empty($fetched_activity)) {
$fetched = true;
$object = JsonLD::compact($fetched_activity); $object = JsonLD::compact($fetched_activity);
$fetched_id = JsonLD::fetchElement($object, '@id'); $fetched_id = JsonLD::fetchElement($object, '@id');
@ -351,7 +354,7 @@ class Receiver
$type = JsonLD::fetchElement($activity, '@type'); $type = JsonLD::fetchElement($activity, '@type');
// Fetch all receivers from to, cc, bto and bcc // Fetch all receivers from to, cc, bto and bcc
$receiverdata = self::getReceivers($activity, $actor); $receiverdata = self::getReceivers($activity, $actor, [], false, $push || $fetched);
$receivers = $reception_types = []; $receivers = $reception_types = [];
foreach ($receiverdata as $key => $data) { foreach ($receiverdata as $key => $data) {
$receivers[$key] = $data['uid']; $receivers[$key] = $data['uid'];
@ -1029,7 +1032,7 @@ class Receiver
$uid = 0; $uid = 0;
$actor = JsonLD::fetchElement($activity, 'as:actor', '@id') ?? ''; $actor = JsonLD::fetchElement($activity, 'as:actor', '@id') ?? '';
$receivers = self::getReceivers($activity, $actor); $receivers = self::getReceivers($activity, $actor, [], false, false);
foreach ($receivers as $receiver) { foreach ($receivers as $receiver) {
if ($receiver['type'] == self::TARGET_GLOBAL) { if ($receiver['type'] == self::TARGET_GLOBAL) {
return 0; return 0;
@ -1078,12 +1081,13 @@ class Receiver
* @param array $activity * @param array $activity
* @param string $actor * @param string $actor
* @param array $tags * @param array $tags
* @param boolean $fetch_unlisted * @param bool $fetch_unlisted
* @param bool $push
* *
* @return array with receivers (user id) * @return array with receivers (user id)
* @throws \Exception * @throws \Exception
*/ */
private static function getReceivers(array $activity, string $actor, array $tags = [], bool $fetch_unlisted = false): array private static function getReceivers(array $activity, string $actor, array $tags, bool $fetch_unlisted, bool $push): array
{ {
$reply = $receivers = $profile = []; $reply = $receivers = $profile = [];
@ -1117,6 +1121,9 @@ class Receiver
$profile = APContact::getByURL($actor); $profile = APContact::getByURL($actor);
$followers = $profile['followers'] ?? ''; $followers = $profile['followers'] ?? '';
$is_forum = ($actor['type'] ?? '') == 'Group'; $is_forum = ($actor['type'] ?? '') == 'Group';
if ($push) {
Contact::updateByUrlIfNeeded($actor);
}
Logger::info('Got actor and followers', ['actor' => $actor, 'followers' => $followers]); Logger::info('Got actor and followers', ['actor' => $actor, 'followers' => $followers]);
} else { } else {
Logger::info('Empty actor', ['activity' => $activity]); Logger::info('Empty actor', ['activity' => $activity]);
@ -2006,7 +2013,7 @@ class Receiver
$object_data['question'] = self::processQuestion($object); $object_data['question'] = self::processQuestion($object);
} }
$receiverdata = self::getReceivers($object, $object_data['actor'] ?? '', $object_data['tags'], true); $receiverdata = self::getReceivers($object, $object_data['actor'] ?? '', $object_data['tags'], true, false);
$receivers = $reception_types = []; $receivers = $reception_types = [];
foreach ($receiverdata as $key => $data) { foreach ($receiverdata as $key => $data) {
$receivers[$key] = $data['uid']; $receivers[$key] = $data['uid'];

View file

@ -534,7 +534,7 @@ class Diaspora
if (is_null($fields)) { if (is_null($fields)) {
$private = true; $private = true;
if (!($fields = self::validPosting($msg))) { if (!($fields = self::validPosting($msg))) {
Logger::warning('Invalid posting', ['msg' => $msg]); Logger::notice('Invalid posting', ['msg' => $msg]);
return false; return false;
} }
} else { } else {
@ -812,6 +812,7 @@ class Diaspora
*/ */
private static function contactByHandle(int $uid, WebFingerUri $uri): array private static function contactByHandle(int $uid, WebFingerUri $uri): array
{ {
Contact::updateByUrlIfNeeded($uri->getAddr());
return Contact::getByURL($uri->getAddr(), null, [], $uid); return Contact::getByURL($uri->getAddr(), null, [], $uid);
} }

View file

@ -22,10 +22,11 @@
namespace Friendica\Worker; namespace Friendica\Worker;
use Friendica\Core\Logger; use Friendica\Core\Logger;
use Friendica\Core\Protocol;
use Friendica\Core\Worker; use Friendica\Core\Worker;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\Contact;
use Friendica\Model\GServer;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
/** /**
@ -56,10 +57,19 @@ class UpdateContacts
} }
$condition = DBA::mergeConditions(["`next-update` < ?", DateTimeFormat::utcNow()], $condition); $condition = DBA::mergeConditions(["`next-update` < ?", DateTimeFormat::utcNow()], $condition);
$contacts = DBA::select('contact', ['id'], $condition, ['order' => ['next-update'], 'limit' => $limit]); $contacts = DBA::select('contact', ['id', 'url', 'gsid', 'baseurl'], $condition, ['order' => ['next-update'], 'limit' => $limit]);
$count = 0; $count = 0;
while ($contact = DBA::fetch($contacts)) { while ($contact = DBA::fetch($contacts)) {
if (Worker::add(['priority' => Worker::PRIORITY_LOW, 'dont_fork' => true], "UpdateContact", $contact['id'])) { if (Contact::isLocal($contact['url'])) {
continue;
}
if ((!empty($contact['gsid']) || !empty($contact['baseurl'])) && GServer::reachable($contact)) {
$stamp = (float)microtime(true);
$success = Contact::updateFromProbe($contact['id']);
Logger::debug('Direct update', ['id' => $contact['id'], 'count' => $count, 'duration' => round((float)microtime(true) - $stamp, 3), 'success' => $success]);
++$count;
} elseif (Worker::add(['priority' => Worker::PRIORITY_LOW, 'dont_fork' => true], 'UpdateContact', $contact['id'])) {
Logger::debug('Update by worker', ['id' => $contact['id'], 'count' => $count]);
++$count; ++$count;
} }
Worker::coolDown(); Worker::coolDown();