Skip to content

Commit dd566f9

Browse files
committed
feat(ContextChat): execute initial import as queued jobs
Signed-off-by: Edward Ly <[email protected]>
1 parent 5e200a4 commit dd566f9

File tree

2 files changed

+100
-80
lines changed

2 files changed

+100
-80
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
7+
* SPDX-License-Identifier: AGPL-3.0-or-later
8+
*/
9+
10+
namespace OCA\Mail\BackgroundJob\ContextChat;
11+
12+
use OCA\Mail\ContextChat\ContextChatProvider;
13+
use OCA\Mail\IMAP\IMAPClientFactory;
14+
use OCA\Mail\Service\MailManager;
15+
use OCP\AppFramework\Utility\ITimeFactory;
16+
use OCP\BackgroundJob\IJobList;
17+
use OCP\BackgroundJob\QueuedJob;
18+
use OCP\ContextChat\ContentItem;
19+
use OCP\ContextChat\IContentManager;
20+
21+
class SubmitContentJob extends QueuedJob {
22+
public function __construct(
23+
ITimeFactory $time,
24+
private MailManager $mailManager,
25+
private IMAPClientFactory $clientFactory,
26+
private ContextChatProvider $contextChatProvider,
27+
private IContentManager $contentManager,
28+
private IJobList $jobList,
29+
) {
30+
parent::__construct($time);
31+
32+
// Only run one instance of this job at a time
33+
$this->setAllowParallelRuns(false);
34+
}
35+
36+
#[\Override]
37+
protected function run($arguments): void {
38+
$client = $this->clientFactory->getClient($arguments['account']);
39+
$items = [];
40+
41+
// Limit number of items to submit for current job
42+
while (count($items) < 100) {
43+
$message = array_pop($arguments['messages']);
44+
if (!$message) {
45+
// No more messages to process
46+
break;
47+
}
48+
49+
// Skip older messages
50+
if ($message->getSentAt() < $arguments['startTime']) {
51+
continue;
52+
}
53+
54+
$imapMessage = $this->mailManager->getImapMessage($client, $arguments['account'], $arguments['mailbox'], $message->getUid(), true);
55+
56+
// Skip encrypted messages
57+
if ($imapMessage->isEncrypted()) {
58+
continue;
59+
}
60+
61+
$fullMessage = $imapMessage->getFullMessage($imapMessage->getUid(), true);
62+
63+
$items[] = new ContentItem(
64+
(string)$message->getId(),
65+
$this->contextChatProvider->getId(),
66+
$imapMessage->getSubject(),
67+
$fullMessage['body'] ?? '',
68+
'E-Mail',
69+
$imapMessage->getSentDate(),
70+
[$arguments['userId']],
71+
);
72+
}
73+
74+
if ($items) {
75+
$this->contentManager->submitContent($this->contextChatProvider->getAppId(), $items);
76+
}
77+
78+
// Schedule next job to process remaining messages
79+
if ($arguments['messages']) {
80+
$this->jobList->add(SubmitContentJob::class, $arguments);
81+
}
82+
}
83+
}

lib/ContextChat/ContextChatProvider.php

Lines changed: 17 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@
1010
namespace OCA\Mail\ContextChat;
1111

1212
use OCA\Mail\AppInfo\Application;
13+
use OCA\Mail\BackgroundJob\ContextChat\SubmitContentJob;
1314
use OCA\Mail\Db\Message;
1415
use OCA\Mail\Db\MessageMapper;
1516
use OCA\Mail\Events\MessageDeletedEvent;
1617
use OCA\Mail\Events\NewMessagesSynchronized;
17-
use OCA\Mail\IMAP\IMAPClientFactory;
1818
use OCA\Mail\Service\AccountService;
1919
use OCA\Mail\Service\MailManager;
20-
use OCP\ContextChat\ContentItem;
20+
use OCP\BackgroundJob\IJobList;
2121
use OCP\ContextChat\Events\ContentProviderRegisterEvent;
2222
use OCP\ContextChat\IContentManager;
2323
use OCP\ContextChat\IContentProvider;
@@ -34,12 +34,12 @@ class ContextChatProvider implements IContentProvider, IEventListener {
3434

3535
public function __construct(
3636
private AccountService $accountService,
37-
private IMAPClientFactory $clientFactory,
3837
private MailManager $mailManager,
3938
private MessageMapper $messageMapper,
4039
private IURLGenerator $urlGenerator,
4140
private IUserManager $userManager,
4241
private IContentManager $contentManager,
42+
private IJobList $jobList,
4343
) {
4444
}
4545

@@ -54,45 +54,14 @@ public function handle(Event $event): void {
5454
}
5555

5656
if ($event instanceof NewMessagesSynchronized) {
57-
$account = $event->getAccount();
58-
$mailbox = $event->getMailbox();
59-
$messages = $event->getMessages();
60-
$userId = $account->getUserId();
61-
$client = $this->clientFactory->getClient($account);
62-
63-
$items = [];
64-
foreach ($messages as $message) {
65-
$imapMessage = $this->mailManager->getImapMessage($client, $account, $mailbox, $message->getUid(), true);
66-
67-
// Skip encrypted messages
68-
if ($imapMessage->isEncrypted()) {
69-
continue;
70-
}
57+
$this->jobList->add(SubmitContentJob::class, [
58+
'userId' => $event->getAccount()->getUserId(),
59+
'account' => $event->getAccount(),
60+
'mailbox' => $event->getMailbox(),
61+
'messages' => $event->getMessages(),
62+
'startTime' => time() - Application::CONTEXT_CHAT_MESSAGE_MAX_AGE,
63+
]);
7164

72-
$fullMessage = $imapMessage->getFullMessage($imapMessage->getUid(), true);
73-
74-
$items[] = new ContentItem(
75-
(string)$message->getId(),
76-
$this->getId(),
77-
$imapMessage->getSubject(),
78-
$fullMessage['body'] ?? '',
79-
'E-Mail',
80-
$imapMessage->getSentDate(),
81-
[$userId],
82-
);
83-
84-
// Submit 100 items at a time
85-
if (count($items) < 100) {
86-
continue;
87-
}
88-
$this->contentManager->submitContent($this->getAppId(), $items);
89-
$items = [];
90-
}
91-
92-
// Submit remaining items
93-
if ($items) {
94-
$this->contentManager->submitContent($this->getAppId(), $items);
95-
}
9665
return;
9766
}
9867

@@ -155,50 +124,18 @@ public function triggerInitialImport(): void {
155124

156125
foreach ($userAccounts as $account) {
157126
$mailboxes = $this->mailManager->getMailboxes($account);
158-
$client = $this->clientFactory->getClient($account);
159127

160128
foreach ($mailboxes as $mailbox) {
161129
$messageUids = $this->messageMapper->findAllUids($mailbox);
162130
$messages = $this->messageMapper->findByUids($mailbox, $messageUids);
163131

164-
$items = [];
165-
foreach ($messages as $message) {
166-
// Skip older messages
167-
if ($message->getSentAt() < $startTime) {
168-
continue;
169-
}
170-
171-
$imapMessage = $this->mailManager->getImapMessage($client, $account, $mailbox, $message->getUid(), true);
172-
173-
// Skip encrypted messages
174-
if ($imapMessage->isEncrypted()) {
175-
continue;
176-
}
177-
178-
$fullMessage = $imapMessage->getFullMessage($imapMessage->getUid(), true);
179-
180-
$items[] = new ContentItem(
181-
(string)$message->getId(),
182-
$this->getId(),
183-
$imapMessage->getSubject(),
184-
$fullMessage['body'] ?? '',
185-
'E-Mail',
186-
$imapMessage->getSentDate(),
187-
[$userId],
188-
);
189-
190-
// Submit 100 items at a time
191-
if (count($items) < 100) {
192-
continue;
193-
}
194-
$this->contentManager->submitContent($this->getAppId(), $items);
195-
$items = [];
196-
}
197-
198-
// Submit remaining items
199-
if ($items) {
200-
$this->contentManager->submitContent($this->getAppId(), $items);
201-
}
132+
$this->jobList->add(SubmitContentJob::class, [
133+
'userId' => $userId,
134+
'account' => $account,
135+
'mailbox' => $mailbox,
136+
'messages' => $messages,
137+
'startTime' => $startTime,
138+
]);
202139
}
203140
}
204141
});

0 commit comments

Comments
 (0)