From e21db0fe6d29f6f752415d8b535206000053734b Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 31 Dec 2022 23:42:00 +0000 Subject: [PATCH] The inbox-status can now be archived for a whole server --- database.sql | 7 ++-- doc/database/db_inbox-status.md | 3 ++ src/Database/PostUpdate.php | 60 ++++++++++++++++++++++++++++++++- src/Model/APContact.php | 22 +++++++----- src/Model/GServer.php | 14 +++++++- src/Util/HTTPSignature.php | 10 +++++- static/dbstructure.config.php | 4 ++- 7 files changed, 105 insertions(+), 15 deletions(-) diff --git a/database.sql b/database.sql index 2d5a1dbaa..19007e6c0 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2023.03-dev (Giant Rhubarb) --- DB_UPDATE_VERSION 1506 +-- DB_UPDATE_VERSION 1507 -- ------------------------------------------ @@ -824,6 +824,7 @@ CREATE TABLE IF NOT EXISTS `inbox-entry-receiver` ( CREATE TABLE IF NOT EXISTS `inbox-status` ( `url` varbinary(383) NOT NULL COMMENT 'URL of the inbox', `uri-id` int unsigned COMMENT 'Item-uri id of inbox url', + `gsid` int unsigned COMMENT 'ID of the related server', `created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'Creation date of this entry', `success` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'Date of the last successful delivery', `failure` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'Date of the last failed delivery', @@ -832,7 +833,9 @@ CREATE TABLE IF NOT EXISTS `inbox-status` ( `shared` boolean NOT NULL DEFAULT '0' COMMENT 'Is it a shared inbox?', PRIMARY KEY(`url`), INDEX `uri-id` (`uri-id`), - FOREIGN KEY (`uri-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE + INDEX `gsid` (`gsid`), + FOREIGN KEY (`uri-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE, + FOREIGN KEY (`gsid`) REFERENCES `gserver` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Status of ActivityPub inboxes'; -- diff --git a/doc/database/db_inbox-status.md b/doc/database/db_inbox-status.md index abcb33da4..ccb28e9bb 100644 --- a/doc/database/db_inbox-status.md +++ b/doc/database/db_inbox-status.md @@ -10,6 +10,7 @@ Fields | -------- | ------------------------------------ | -------------- | ---- | --- | ------------------- | ----- | | url | URL of the inbox | varbinary(383) | NO | PRI | NULL | | | uri-id | Item-uri id of inbox url | int unsigned | YES | | NULL | | +| gsid | ID of the related server | int unsigned | YES | | NULL | | | created | Creation date of this entry | datetime | NO | | 0001-01-01 00:00:00 | | | success | Date of the last successful delivery | datetime | NO | | 0001-01-01 00:00:00 | | | failure | Date of the last failed delivery | datetime | NO | | 0001-01-01 00:00:00 | | @@ -24,6 +25,7 @@ Indexes | ------- | ------ | | PRIMARY | url | | uri-id | uri-id | +| gsid | gsid | Foreign Keys ------------ @@ -31,5 +33,6 @@ Foreign Keys | Field | Target Table | Target Field | |-------|--------------|--------------| | uri-id | [item-uri](help/database/db_item-uri) | id | +| gsid | [gserver](help/database/db_gserver) | id | Return to [database documentation](help/database) diff --git a/src/Database/PostUpdate.php b/src/Database/PostUpdate.php index d54c3f221..cfb6b1569 100644 --- a/src/Database/PostUpdate.php +++ b/src/Database/PostUpdate.php @@ -50,7 +50,7 @@ class PostUpdate // Needed for the helper function to read from the legacy term table const OBJECT_TYPE_POST = 1; - const VERSION = 1484; + const VERSION = 1507; /** * Calls the post update functions @@ -117,6 +117,9 @@ class PostUpdate if (!self::update1484()) { return false; } + if (!self::update1507()) { + return false; + } return true; } @@ -1184,4 +1187,59 @@ class PostUpdate return false; } + + /** + * update the "gsid" (global server id) field in the inbox-status table + * + * @return bool "true" when the job is done + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws \ImagickException + */ + private static function update1507() + { + // Was the script completed? + if (DI::keyValue()->get('post_update_version') >= 1507) { + return true; + } + + $id = DI::keyValue()->get('post_update_version_1507_id') ?? ''; + + Logger::info('Start', ['apcontact' => $id]); + + $start_id = $id; + $rows = 0; + $condition = ["`url` > ? AND NOT `gsid` IS NULL", $id]; + $params = ['order' => ['url'], 'limit' => 10000]; + $apcontacts = DBA::select('apcontact', ['url', 'gsid', 'sharedinbox', 'inbox'], $condition, $params); + + if (DBA::errorNo() != 0) { + Logger::error('Database error', ['no' => DBA::errorNo(), 'message' => DBA::errorMessage()]); + return false; + } + + while ($apcontact = DBA::fetch($apcontacts)) { + $id = $apcontact['url']; + + $inbox = [$apcontact['inbox']]; + if (!empty($apcontact['sharedinbox'])) { + $inbox[] = $apcontact['sharedinbox']; + } + $condition = DBA::mergeConditions(['url' => $inbox], ["`gsid` IS NULL"]); + DBA::update('inbox-status', ['gsid' => $apcontact['gsid']], $condition); + ++$rows; + } + DBA::close($apcontacts); + + DI::keyValue()->set('post_update_version_1507_id', $id); + + Logger::info('Processed', ['rows' => $rows, 'last' => $id]); + + if ($start_id == $id) { + DI::keyValue()->set('post_update_version', 1507); + Logger::info('Done'); + return true; + } + + return false; + } } diff --git a/src/Model/APContact.php b/src/Model/APContact.php index fd748f1cd..851916de9 100644 --- a/src/Model/APContact.php +++ b/src/Model/APContact.php @@ -226,14 +226,11 @@ class APContact $apcontact['following'] = JsonLD::fetchElement($compacted, 'as:following', '@id'); $apcontact['followers'] = JsonLD::fetchElement($compacted, 'as:followers', '@id'); $apcontact['inbox'] = (JsonLD::fetchElement($compacted, 'ldp:inbox', '@id') ?? ''); - self::unarchiveInbox($apcontact['inbox'], false); - $apcontact['outbox'] = JsonLD::fetchElement($compacted, 'as:outbox', '@id'); $apcontact['sharedinbox'] = ''; if (!empty($compacted['as:endpoints'])) { $apcontact['sharedinbox'] = (JsonLD::fetchElement($compacted['as:endpoints'], 'as:sharedInbox', '@id') ?? ''); - self::unarchiveInbox($apcontact['sharedinbox'], true); } $apcontact['featured'] = JsonLD::fetchElement($compacted, 'toot:featured', '@id'); @@ -427,6 +424,12 @@ class APContact $apcontact['gsid'] = null; } + self::unarchiveInbox($apcontact['inbox'], false, $apcontact['gsid']); + + if (!empty($apcontact['sharedinbox'])) { + self::unarchiveInbox($apcontact['sharedinbox'], true, $apcontact['gsid']); + } + if ($apcontact['url'] == $apcontact['alias']) { $apcontact['alias'] = null; } @@ -517,7 +520,7 @@ class APContact { if (!empty($apcontact['inbox'])) { Logger::info('Set inbox status to failure', ['inbox' => $apcontact['inbox']]); - HTTPSignature::setInboxStatus($apcontact['inbox'], false); + HTTPSignature::setInboxStatus($apcontact['inbox'], false, false, $apcontact['gsid']); } if (!empty($apcontact['sharedinbox'])) { @@ -527,7 +530,7 @@ class APContact if (!$available) { // If all known personal inboxes are failing then set their shared inbox to failure as well Logger::info('Set shared inbox status to failure', ['sharedinbox' => $apcontact['sharedinbox']]); - HTTPSignature::setInboxStatus($apcontact['sharedinbox'], false, true); + HTTPSignature::setInboxStatus($apcontact['sharedinbox'], false, true, $apcontact['gsid']); } } } @@ -542,11 +545,11 @@ class APContact { if (!empty($apcontact['inbox'])) { Logger::info('Set inbox status to success', ['inbox' => $apcontact['inbox']]); - HTTPSignature::setInboxStatus($apcontact['inbox'], true); + HTTPSignature::setInboxStatus($apcontact['inbox'], true, false, $apcontact['gsid']); } if (!empty($apcontact['sharedinbox'])) { Logger::info('Set shared inbox status to success', ['sharedinbox' => $apcontact['sharedinbox']]); - HTTPSignature::setInboxStatus($apcontact['sharedinbox'], true, true); + HTTPSignature::setInboxStatus($apcontact['sharedinbox'], true, true, $apcontact['gsid']); } } @@ -555,15 +558,16 @@ class APContact * * @param string $url inbox url * @param boolean $shared Shared Inbox + * @param int $gsid Global server id * @return void */ - private static function unarchiveInbox(string $url, bool $shared) + private static function unarchiveInbox(string $url, bool $shared, int $gsid = null) { if (empty($url)) { return; } - HTTPSignature::setInboxStatus($url, true, $shared); + HTTPSignature::setInboxStatus($url, true, $shared, $gsid); } /** diff --git a/src/Model/GServer.php b/src/Model/GServer.php index 477b1f323..86fb78f79 100644 --- a/src/Model/GServer.php +++ b/src/Model/GServer.php @@ -408,7 +408,7 @@ class GServer ['nurl' => Strings::normaliseLink($url)]); Logger::info('Set failed status for existing server', ['url' => $url]); if (self::isDefunct($gserver)) { - Contact::update(['archive' => true], ['gsid' => $gserver['id']]); + self::archiveContacts($gserver['id']); } return; } @@ -418,6 +418,18 @@ class GServer Logger::info('Set failed status for new server', ['url' => $url]); } + /** + * Archive server related contacts and inboxes + * + * @param integer $gsid + * @return void + */ + private static function archiveContacts(int $gsid) + { + Contact::update(['archive' => true], ['gsid' => $gsid]); + DBA::update('inbox-status', ['archive' => true], ['gsid' => $gsid]); + } + /** * Remove unwanted content from the given URL * diff --git a/src/Util/HTTPSignature.php b/src/Util/HTTPSignature.php index 84219b311..0543cbcdf 100644 --- a/src/Util/HTTPSignature.php +++ b/src/Util/HTTPSignature.php @@ -332,15 +332,19 @@ class HTTPSignature * @param string $url The URL of the inbox * @param boolean $success Transmission status * @param boolean $shared The inbox is a shared inbox + * @param int $gsid Server ID * @throws \Exception */ - static public function setInboxStatus(string $url, bool $success, bool $shared = false) + static public function setInboxStatus(string $url, bool $success, bool $shared = false, int $gsid = null) { $now = DateTimeFormat::utcNow(); $status = DBA::selectFirst('inbox-status', [], ['url' => $url]); if (!DBA::isResult($status)) { $insertFields = ['url' => $url, 'uri-id' => ItemURI::getIdByURI($url), 'created' => $now, 'shared' => $shared]; + if (!empty($gsid)) { + $insertFields['gsid'] = $gsid; + } if (!DBA::insert('inbox-status', $insertFields, Database::INSERT_IGNORE)) { Logger::warning('Unable to insert inbox-status row', $insertFields); return; @@ -355,6 +359,10 @@ class HTTPSignature $fields = ['failure' => $now]; } + if (!empty($gsid)) { + $fields['gsid'] = $gsid; + } + if ($status['failure'] > DBA::NULL_DATETIME) { $new_previous_stamp = strtotime($status['failure']); $old_previous_stamp = strtotime($status['previous']); diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index cf6131c2e..7736dafd4 100644 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -55,7 +55,7 @@ use Friendica\Database\DBA; if (!defined('DB_UPDATE_VERSION')) { - define('DB_UPDATE_VERSION', 1506); + define('DB_UPDATE_VERSION', 1507); } return [ @@ -872,6 +872,7 @@ return [ "fields" => [ "url" => ["type" => "varbinary(383)", "not null" => "1", "primary" => "1", "comment" => "URL of the inbox"], "uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Item-uri id of inbox url"], + "gsid" => ["type" => "int unsigned", "foreign" => ["gserver" => "id", "on delete" => "restrict"], "comment" => "ID of the related server"], "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Creation date of this entry"], "success" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date of the last successful delivery"], "failure" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date of the last failed delivery"], @@ -882,6 +883,7 @@ return [ "indexes" => [ "PRIMARY" => ["url"], "uri-id" => ["uri-id"], + "gsid" => ["gsid"], ] ], "intro" => [