Skip to content

Commit f6b8f04

Browse files
committed
fix: improve messaging migration - remove target migration, fix subscriber resolution and message search
- Remove target export/import from messaging group (email/sms auto-created during user migration, push targets to be added under auth group separately) - Fix createSubscriber() to resolve targets by providerType switch (push: direct ID, email/sms: userId + providerType) - Fix createMessage() to include $permissions and search field matching server's messageSearch filter - Remove targetUserMap and resolveMessageTargets (unnecessary indirection) - Extract createTopic() and createProvider() into dedicated methods with proper return types
1 parent 3583aac commit f6b8f04

File tree

4 files changed

+68
-110
lines changed

4 files changed

+68
-110
lines changed

src/Migration/Destinations/Appwrite.php

Lines changed: 49 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1602,11 +1602,7 @@ public function importMessagingResource(Resource $resource): Resource
16021602
break;
16031603
case Resource::TYPE_TOPIC:
16041604
/** @var Topic $resource */
1605-
$this->messaging->createTopic(
1606-
$resource->getId(),
1607-
$resource->getTopicName(),
1608-
$resource->getSubscribe(),
1609-
);
1605+
$this->createTopic($resource);
16101606
break;
16111607
case Resource::TYPE_SUBSCRIBER:
16121608
/** @var Subscriber $resource */
@@ -1767,7 +1763,7 @@ public function importSiteResource(Resource $resource): Resource
17671763
* @throws AppwriteException
17681764
* @throws \Exception
17691765
*/
1770-
protected function createProvider(Provider $resource): bool
1766+
protected function createProvider(Provider $resource): void
17711767
{
17721768
$credentials = $resource->getCredentials();
17731769
$options = $resource->getOptions();
@@ -1886,27 +1882,40 @@ protected function createProvider(Provider $resource): bool
18861882
),
18871883
default => throw new \Exception('Unknown provider: ' . $resource->getProvider()),
18881884
};
1885+
}
18891886

1890-
return true;
1887+
/**
1888+
* @throws AppwriteException
1889+
*/
1890+
protected function createTopic(Topic $resource): void
1891+
{
1892+
$this->messaging->createTopic(
1893+
$resource->getId(),
1894+
$resource->getTopicName(),
1895+
$resource->getSubscribe(),
1896+
);
18911897
}
18921898

18931899
/**
1894-
* @throws \Exception
1900+
* @throws AuthorizationException
1901+
* @throws StructureException
1902+
* @throws DatabaseException|\Exception
18951903
*/
18961904
protected function createSubscriber(Subscriber $resource): void
18971905
{
1898-
$target = $this->database->find('targets', [
1899-
Query::equal('userId', [$resource->getUserId()]),
1900-
Query::equal('providerType', [$resource->getProviderType()]),
1901-
Query::limit(1),
1902-
]);
1906+
$target = match ($resource->getProviderType()) {
1907+
'push' => $this->database->getDocument('targets', $resource->getTargetId()),
1908+
'email', 'sms' => $this->database->findOne('targets', [
1909+
Query::equal('userId', [$resource->getUserId()]),
1910+
Query::equal('providerType', [$resource->getProviderType()]),
1911+
]),
1912+
default => throw new \Exception('Unknown provider type: ' . $resource->getProviderType()),
1913+
};
19031914

1904-
if (empty($target)) {
1905-
throw new \Exception('No matching target found for subscriber ' . $resource->getId() . ' with providerType ' . $resource->getProviderType());
1915+
if (!$target || $target->isEmpty()) {
1916+
throw new \Exception('Target not found for subscriber: ' . $resource->getId());
19061917
}
19071918

1908-
$target = $target[0];
1909-
19101919
$topic = $this->database->getDocument('topics', $resource->getTopicId());
19111920
if ($topic->isEmpty()) {
19121921
throw new \Exception('Topic not found: ' . $resource->getTopicId());
@@ -1957,16 +1966,18 @@ protected function createSubscriber(Subscriber $resource): void
19571966
* @throws AppwriteException
19581967
* @throws \Exception
19591968
*/
1960-
protected function createMessage(Message $resource): bool
1969+
protected function createMessage(Message $resource): void
19611970
{
1962-
$resolvedTargets = $this->resolveMessageTargets($resource);
1971+
$resolvedTargets = $resource->getTargets();
19631972
$status = $resource->getMessageStatus();
19641973

19651974
if ($status === 'scheduled') {
19661975
$scheduledAt = $resource->getScheduledAt();
19671976

19681977
if (!empty($scheduledAt) && new \DateTime($scheduledAt) > new \DateTime()) {
1969-
return $this->createScheduledMessage($resource, $resolvedTargets);
1978+
$this->createScheduledMessage($resource, $resolvedTargets);
1979+
1980+
return;
19701981
}
19711982

19721983
$status = 'draft';
@@ -1979,10 +1990,19 @@ protected function createMessage(Message $resource): bool
19791990
$createdAt = $this->normalizeDateTime($resource->getCreatedAt());
19801991
$updatedAt = $this->normalizeDateTime($resource->getUpdatedAt(), $createdAt);
19811992

1993+
$data = $resource->getData();
1994+
$searchContent = match ($resource->getProviderType()) {
1995+
'email' => $data['subject'] ?? '',
1996+
'sms' => $data['content'] ?? '',
1997+
'push' => $data['title'] ?? '',
1998+
default => '',
1999+
};
2000+
19822001
$this->database->createDocument('messages', new UtopiaDocument([
19832002
'$id' => $resource->getId(),
19842003
'$createdAt' => $createdAt,
19852004
'$updatedAt' => $updatedAt,
2005+
'$permissions' => [],
19862006
'providerType' => $resource->getProviderType(),
19872007
'topics' => $resource->getTopics(),
19882008
'users' => $resource->getUsers(),
@@ -1991,19 +2011,24 @@ protected function createMessage(Message $resource): bool
19912011
'deliveredAt' => $resource->getDeliveredAt() ?: null,
19922012
'deliveryErrors' => $resource->getDeliveryErrors(),
19932013
'deliveredTotal' => $resource->getDeliveredTotal(),
1994-
'data' => $resource->getData(),
2014+
'data' => $data,
19952015
'status' => $status,
2016+
'search' => implode(' ', array_filter([
2017+
$resource->getId(),
2018+
$data['description'] ?? '',
2019+
$status,
2020+
$searchContent,
2021+
$resource->getProviderType(),
2022+
])),
19962023
]));
1997-
1998-
return true;
19992024
}
20002025

20012026
/**
20022027
* @param array<string> $resolvedTargets
20032028
* @throws AppwriteException
20042029
* @throws \Exception
20052030
*/
2006-
protected function createScheduledMessage(Message $resource, array $resolvedTargets): bool
2031+
protected function createScheduledMessage(Message $resource, array $resolvedTargets): void
20072032
{
20082033
$data = $resource->getData();
20092034
$topics = $resource->getTopics() ?: null;
@@ -2058,34 +2083,8 @@ protected function createScheduledMessage(Message $resource, array $resolvedTarg
20582083
),
20592084
default => throw new \Exception('Unknown provider type: ' . $resource->getProviderType()),
20602085
};
2061-
2062-
return true;
2063-
}
2064-
2065-
/**
2066-
* @return array<string>
2067-
*/
2068-
private function resolveMessageTargets(Message $resource): array
2069-
{
2070-
$targetUserMap = $resource->getTargetUserMap();
2071-
2072-
$userIds = array_values(array_unique(array_filter(
2073-
array_map(fn ($sourceTargetId) => $targetUserMap[$sourceTargetId] ?? null, $resource->getTargets())
2074-
)));
2075-
2076-
if (empty($userIds)) {
2077-
return [];
2078-
}
2079-
2080-
$targets = $this->database->find('targets', [
2081-
Query::equal('userId', $userIds),
2082-
Query::equal('providerType', [$resource->getProviderType()]),
2083-
]);
2084-
2085-
return array_map(fn (UtopiaDocument $target) => $target->getId(), $targets);
20862086
}
20872087

2088-
20892088
private function importSiteDeployment(SiteDeployment $deployment): Resource
20902089
{
20912090
$site = $deployment->getSite();

src/Migration/Resources/Messaging/Message.php

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ class Message extends Resource
1919
* @param string $deliveredAt
2020
* @param array<string> $deliveryErrors
2121
* @param int $deliveredTotal
22-
* @param array<string, string> $targetUserMap Source target ID => source user ID mapping for ID resolution
2322
*/
2423
public function __construct(
2524
string $id,
@@ -33,7 +32,6 @@ public function __construct(
3332
private readonly string $deliveredAt = '',
3433
private readonly array $deliveryErrors = [],
3534
private readonly int $deliveredTotal = 0,
36-
private readonly array $targetUserMap = [],
3735
protected string $createdAt = '',
3836
protected string $updatedAt = '',
3937
) {
@@ -58,7 +56,6 @@ public static function fromArray(array $array): self
5856
$array['deliveredAt'] ?? '',
5957
$array['deliveryErrors'] ?? [],
6058
$array['deliveredTotal'] ?? 0,
61-
$array['targetUserMap'] ?? [],
6259
$array['createdAt'] ?? '',
6360
$array['updatedAt'] ?? '',
6461
);
@@ -81,7 +78,6 @@ public function jsonSerialize(): array
8178
'deliveredAt' => $this->deliveredAt,
8279
'deliveryErrors' => $this->deliveryErrors,
8380
'deliveredTotal' => $this->deliveredTotal,
84-
'targetUserMap' => $this->targetUserMap,
8581
'createdAt' => $this->createdAt,
8682
'updatedAt' => $this->updatedAt,
8783
];
@@ -161,12 +157,4 @@ public function getDeliveredTotal(): int
161157
{
162158
return $this->deliveredTotal;
163159
}
164-
165-
/**
166-
* @return array<string, string>
167-
*/
168-
public function getTargetUserMap(): array
169-
{
170-
return $this->targetUserMap;
171-
}
172160
}

src/Migration/Sources/Appwrite.php

Lines changed: 13 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1804,6 +1804,7 @@ private function exportDeploymentData(Func $func, array $deployment): void
18041804
* @param array<string> $resources
18051805
* @param array<string, int> $report
18061806
* @param array<string, array<string>> $resourceIds
1807+
* @throws AppwriteException
18071808
*/
18081809
private function reportMessaging(array $resources, array &$report, array $resourceIds = []): void
18091810
{
@@ -1922,7 +1923,9 @@ protected function exportGroupMessaging(int $batchSize, array $resources): void
19221923
}
19231924
}
19241925

1925-
1926+
/**
1927+
* @throws AppwriteException
1928+
*/
19261929
private function exportProviders(int $batchSize): void
19271930
{
19281931
$lastDocument = null;
@@ -1971,6 +1974,9 @@ private function exportProviders(int $batchSize): void
19711974
}
19721975
}
19731976

1977+
/**
1978+
* @throws AppwriteException
1979+
*/
19741980
private function exportTopics(int $batchSize): void
19751981
{
19761982
$lastDocument = null;
@@ -2015,6 +2021,9 @@ private function exportTopics(int $batchSize): void
20152021
}
20162022
}
20172023

2024+
/**
2025+
* @throws AppwriteException
2026+
*/
20182027
private function exportSubscribers(int $batchSize): void
20192028
{
20202029
$topics = $this->cache->get(Topic::getName());
@@ -2062,9 +2071,11 @@ private function exportSubscribers(int $batchSize): void
20622071
}
20632072
}
20642073

2074+
/**
2075+
* @throws AppwriteException
2076+
*/
20652077
private function exportMessages(int $batchSize): void
20662078
{
2067-
$targetUserMap = $this->buildTargetUserMap();
20682079
$lastDocument = null;
20692080

20702081
while (true) {
@@ -2088,13 +2099,6 @@ private function exportMessages(int $batchSize): void
20882099
}
20892100

20902101
foreach ($response['messages'] as $message) {
2091-
$messageTargetMap = [];
2092-
foreach ($message['targets'] ?? [] as $targetId) {
2093-
if (isset($targetUserMap[$targetId])) {
2094-
$messageTargetMap[$targetId] = $targetUserMap[$targetId];
2095-
}
2096-
}
2097-
20982102
$messages[] = new Message(
20992103
$message['$id'],
21002104
$message['providerType'] ?? '',
@@ -2107,7 +2111,6 @@ private function exportMessages(int $batchSize): void
21072111
$message['deliveredAt'] ?? '',
21082112
$message['deliveryErrors'] ?? [],
21092113
$message['deliveredTotal'] ?? 0,
2110-
$messageTargetMap,
21112114
$message['$createdAt'] ?? '',
21122115
$message['$updatedAt'] ?? '',
21132116
);
@@ -2123,44 +2126,6 @@ private function exportMessages(int $batchSize): void
21232126
}
21242127
}
21252128

2126-
/**
2127-
* Build a map of source target ID => source user ID
2128-
* by iterating cached users and listing their targets.
2129-
*
2130-
* @return array<string, string>
2131-
*/
2132-
private function buildTargetUserMap(): array
2133-
{
2134-
$map = [];
2135-
$users = $this->cache->get(User::getName());
2136-
2137-
foreach ($users as $user) {
2138-
/** @var User $user */
2139-
$lastTarget = null;
2140-
2141-
while (true) {
2142-
$queries = [Query::limit(self::DEFAULT_PAGE_LIMIT)];
2143-
2144-
if ($lastTarget !== null) {
2145-
$queries[] = Query::cursorAfter($lastTarget);
2146-
}
2147-
2148-
$response = $this->users->listTargets($user->getId(), $queries);
2149-
2150-
foreach ($response['targets'] as $target) {
2151-
$map[$target['$id']] = $user->getId();
2152-
$lastTarget = $target['$id'];
2153-
}
2154-
2155-
if (\count($response['targets']) < self::DEFAULT_PAGE_LIMIT) {
2156-
break;
2157-
}
2158-
}
2159-
}
2160-
2161-
return $map;
2162-
}
2163-
21642129
/**
21652130
* @throws AppwriteException
21662131
*/

tests/Migration/Unit/Adapters/MockSource.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,12 @@ protected function exportGroupFunctions(int $batchSize, array $resources): void
165165
}
166166
}
167167

168+
/**
169+
* Export Messaging Group
170+
*
171+
* @param int $batchSize Max 100
172+
* @param string[] $resources Resources to export
173+
*/
168174
protected function exportGroupMessaging(int $batchSize, array $resources): void
169175
{
170176
foreach (Transfer::GROUP_MESSAGING_RESOURCES as $resource) {

0 commit comments

Comments
 (0)