From 49654c0d99605a75d3fc8dc05727abcb7b285e5c Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sat, 31 Dec 2022 14:27:42 -0500 Subject: [PATCH] Create entity-related classes for delivery-queue table --- src/DI.php | 14 +++ .../Collection/DeliveryQueueAggregates.php | 44 +++++++ .../Collection/DeliveryQueueItems.php | 44 +++++++ .../Entity/DeliveryQueueAggregate.php | 40 +++++++ src/Federation/Entity/DeliveryQueueItem.php | 62 ++++++++++ src/Federation/Factory/DeliveryQueueItem.php | 55 +++++++++ .../Repository/DeliveryQueueItem.php | 113 ++++++++++++++++++ 7 files changed, 372 insertions(+) create mode 100644 src/Federation/Collection/DeliveryQueueAggregates.php create mode 100644 src/Federation/Collection/DeliveryQueueItems.php create mode 100644 src/Federation/Entity/DeliveryQueueAggregate.php create mode 100644 src/Federation/Entity/DeliveryQueueItem.php create mode 100644 src/Federation/Factory/DeliveryQueueItem.php create mode 100644 src/Federation/Repository/DeliveryQueueItem.php diff --git a/src/DI.php b/src/DI.php index 261455385a..0ef18a1aa3 100644 --- a/src/DI.php +++ b/src/DI.php @@ -602,6 +602,20 @@ abstract class DI return self::$dice->create(Navigation\Notifications\Factory\FormattedNavNotification::class); } + // + // "Federation" namespace instances + // + + public static function deliveryQueueItemFactory(): Federation\Factory\DeliveryQueueItem + { + return self::$dice->create(Federation\Factory\DeliveryQueueItem::class); + } + + public static function deliveryQueueItemRepo(): Federation\Repository\DeliveryQueueItem + { + return self::$dice->create(Federation\Repository\DeliveryQueueItem::class); + } + // // "Protocol" namespace instances // diff --git a/src/Federation/Collection/DeliveryQueueAggregates.php b/src/Federation/Collection/DeliveryQueueAggregates.php new file mode 100644 index 0000000000..60f07675af --- /dev/null +++ b/src/Federation/Collection/DeliveryQueueAggregates.php @@ -0,0 +1,44 @@ +. + * + */ + +namespace Friendica\Federation\Collection; + +use Friendica\Federation\Entity; + +final class DeliveryQueueAggregates extends \Friendica\BaseCollection +{ + /** + * @param Entity\DeliveryQueueAggregate[] $entities + * @param int|null $totalCount + */ + public function __construct(array $entities = [], int $totalCount = null) + { + parent::__construct($entities, $totalCount); + } + + /** + * @return Entity\DeliveryQueueAggregate + */ + public function current(): Entity\DeliveryQueueAggregate + { + return parent::current(); + } +} diff --git a/src/Federation/Collection/DeliveryQueueItems.php b/src/Federation/Collection/DeliveryQueueItems.php new file mode 100644 index 0000000000..a41f7b07cc --- /dev/null +++ b/src/Federation/Collection/DeliveryQueueItems.php @@ -0,0 +1,44 @@ +. + * + */ + +namespace Friendica\Federation\Collection; + +use Friendica\Federation\Entity; + +final class DeliveryQueueItems extends \Friendica\BaseCollection +{ + /** + * @param Entity\DeliveryQueueItem[] $entities + * @param int|null $totalCount + */ + public function __construct(array $entities = [], int $totalCount = null) + { + parent::__construct($entities, $totalCount); + } + + /** + * @return Entity\DeliveryQueueItem + */ + public function current(): Entity\DeliveryQueueItem + { + return parent::current(); + } +} diff --git a/src/Federation/Entity/DeliveryQueueAggregate.php b/src/Federation/Entity/DeliveryQueueAggregate.php new file mode 100644 index 0000000000..9be4b0e739 --- /dev/null +++ b/src/Federation/Entity/DeliveryQueueAggregate.php @@ -0,0 +1,40 @@ +. + * + */ + +namespace Friendica\Federation\Entity; + +/** + * @property-read int $targetServerId + * @property-read int $failed Maximum number of delivery failures among the delivery queue items targeting the server + */ +final class DeliveryQueueAggregate extends \Friendica\BaseEntity +{ + /** @var int */ + protected $targetServerId; + /** @var int */ + protected $failed; + + public function __construct(int $targetServerId, int $failed) + { + $this->targetServerId = $targetServerId; + $this->failed = $failed; + } +} diff --git a/src/Federation/Entity/DeliveryQueueItem.php b/src/Federation/Entity/DeliveryQueueItem.php new file mode 100644 index 0000000000..aa9cd5b831 --- /dev/null +++ b/src/Federation/Entity/DeliveryQueueItem.php @@ -0,0 +1,62 @@ +. + * + */ + +namespace Friendica\Federation\Entity; + +use DateTimeImmutable; + +/** + * @property-read int $targetServerId + * @property-read int $postUriId + * @property-read DateTimeImmutable $created + * @property-read string $command One of the Protocol\Delivery command constant values + * @property-read int $targetContactId + * @property-read int $senderUserId + * @property-read int $failed Number of delivery failures for this post and target server + */ +final class DeliveryQueueItem extends \Friendica\BaseEntity +{ + /** @var int */ + protected $targetServerId; + /** @var int */ + protected $postUriId; + /** @var DateTimeImmutable */ + protected $created; + /** @var string */ + protected $command; + /** @var int */ + protected $targetContactId; + /** @var int */ + protected $senderUserId; + /** @var int */ + protected $failed; + + public function __construct(int $targetServerId, int $postUriId, DateTimeImmutable $created, string $command, int $targetContactId, int $senderUserId, int $failed = 0) + { + $this->targetServerId = $targetServerId; + $this->postUriId = $postUriId; + $this->created = $created; + $this->command = $command; + $this->targetContactId = $targetContactId; + $this->senderUserId = $senderUserId; + $this->failed = $failed; + } +} diff --git a/src/Federation/Factory/DeliveryQueueItem.php b/src/Federation/Factory/DeliveryQueueItem.php new file mode 100644 index 0000000000..2559e81650 --- /dev/null +++ b/src/Federation/Factory/DeliveryQueueItem.php @@ -0,0 +1,55 @@ +. + * + */ + +namespace Friendica\Federation\Factory; + +use Friendica\Federation\Entity; + +final class DeliveryQueueItem extends \Friendica\BaseFactory implements \Friendica\Capabilities\ICanCreateFromTableRow +{ + /** + * @inheritDoc + */ + public function createFromTableRow(array $row): Entity\DeliveryQueueItem + { + return new Entity\DeliveryQueueItem( + $row['gsid'], + $row['uri-id'], + new \DateTimeImmutable($row['created']), + $row['command'], + $row['cid'], + $row['uid'], + $row['failed'] + ); + } + + public function createFromDelivery(string $cmd, int $uri_id, \DateTimeImmutable $created, int $cid, int $gsid, int $uid): Entity\DeliveryQueueItem + { + return new Entity\DeliveryQueueItem( + $gsid, + $uri_id, + $created, + $cmd, + $cid, + $uid + ); + } +} diff --git a/src/Federation/Repository/DeliveryQueueItem.php b/src/Federation/Repository/DeliveryQueueItem.php new file mode 100644 index 0000000000..815cf89b50 --- /dev/null +++ b/src/Federation/Repository/DeliveryQueueItem.php @@ -0,0 +1,113 @@ +. + * + */ + +namespace Friendica\Federation\Repository; + +use Friendica\Database\Database; +use Friendica\Database\DBA; +use Friendica\Federation\Collection; +use Friendica\Federation\Entity; +use Friendica\Federation\Factory; +use Friendica\Util\DateTimeFormat; +use Psr\Log\LoggerInterface; + +final class DeliveryQueueItem extends \Friendica\BaseRepository +{ + protected static $table_name = 'delivery-queue'; + + public function __construct(Database $database, LoggerInterface $logger, Factory\DeliveryQueueItem $factory) + { + parent::__construct($database, $logger, $factory); + } + + public function selectByServerId(int $gsid, int $maxFailedCount): Collection\DeliveryQueueItems + { + $Entities = new Collection\DeliveryQueueItems(); + + $deliveryQueueItems = $this->db->select( + self::$table_name, + [], + ["`gsid` = ? AND `failed` < ?", $gsid, $maxFailedCount], + ['order' => ['created']] + ); + while ($deliveryQueueItem = $this->db->fetch($deliveryQueueItems)) { + $Entities[] = $this->factory->createFromTableRow($deliveryQueueItem); + } + + $this->db->close($deliveryQueueItems); + + return $Entities; + } + + public function selectAggregateByServerId(): Collection\DeliveryQueueAggregates + { + $Entities = new Collection\DeliveryQueueAggregates(); + + $deliveryQueueAggregates = $this->db->p("SELECT `gsid`, MAX(`failed`) AS `failed` FROM " . DBA::buildTableString([self::$table_name]) . " GROUP BY `gsid` ORDER BY RAND()"); + while ($deliveryQueueAggregate = $this->db->fetch($deliveryQueueAggregates)) { + $Entities[] = new Entity\DeliveryQueueAggregate($deliveryQueueAggregate['gsid'], $deliveryQueueAggregate['failed']); + } + + $this->db->close($deliveryQueueAggregates); + + return $Entities; + } + + public function save(Entity\DeliveryQueueItem $deliveryQueueItem) + { + $fields = [ + 'gsid' => $deliveryQueueItem->targetServerId, + 'uri-id' => $deliveryQueueItem->postUriId, + 'created' => $deliveryQueueItem->created->format(DateTimeFormat::MYSQL), + 'command' => $deliveryQueueItem->command, + 'cid' => $deliveryQueueItem->targetContactId, + 'uid' => $deliveryQueueItem->senderUserId, + 'failed' => $deliveryQueueItem->failed, + ]; + + $this->db->insert(self::$table_name, $fields, Database::INSERT_UPDATE); + } + + public function remove(Entity\DeliveryQueueItem $deliveryQueueItem): bool + { + return $this->db->delete(self::$table_name, ['uri-id' => $deliveryQueueItem->postUriId, 'gsid' => $deliveryQueueItem->targetServerId]); + } + + public function removeFailedByServerId(int $gsid, int $failedThreshold): bool + { + return $this->db->delete(self::$table_name, ["`gsid` = ? AND `failed` >= ?", $gsid, $failedThreshold]); + } + + public function incrementFailed(Entity\DeliveryQueueItem $deliveryQueueItem): bool + { + return $this->db->e(" + UPDATE " . DBA::buildTableString([self::$table_name]) . " + SET `failed` = `failed` + 1 + WHERE `uri-id` = ? AND `gsid` = ?", + $deliveryQueueItem->postUriId, $deliveryQueueItem->targetServerId + ); + } + + public function optimizeStorage(): bool + { + return $this->db->e("OPTIMIZE TABLE " . DBA::buildTableString([self::$table_name])); + } +}