diff options
author | call-me-matt <nextcloud@matthiasheinisch.de> | 2020-08-12 00:38:06 +0300 |
---|---|---|
committer | call-me-matt <nextcloud@matthiasheinisch.de> | 2020-08-14 13:25:04 +0300 |
commit | 1831bc4470ff551f16236c3f6d89368c8e6a4df2 (patch) | |
tree | dfd647e4925ee9596be99c2878b4decb7863373a /lib/Service | |
parent | 752bb14cd88acb200582724aa430887a76b5b864 (diff) |
update social avatars in chunks
Signed-off-by: call-me-matt <nextcloud@matthiasheinisch.de>
Diffstat (limited to 'lib/Service')
-rw-r--r-- | lib/Service/SocialApiService.php | 80 |
1 files changed, 70 insertions, 10 deletions
diff --git a/lib/Service/SocialApiService.php b/lib/Service/SocialApiService.php index f0339c07..0d08921a 100644 --- a/lib/Service/SocialApiService.php +++ b/lib/Service/SocialApiService.php @@ -38,6 +38,7 @@ use OCA\DAV\CardDAV\CardDavBackend; use OCA\DAV\CardDAV\ContactsManager; use OCP\IURLGenerator; use OCP\IL10N; +use OCP\AppFramework\Utility\ITimeFactory; class SocialApiService { private $appName; @@ -55,6 +56,8 @@ class SocialApiService { private $urlGen; /** @var CardDavBackend */ private $davBackend; + /** @var ITimeFactory */ + private $timeFactory; public function __construct( @@ -64,7 +67,8 @@ class SocialApiService { IClientService $clientService, IL10N $l10n, IURLGenerator $urlGen, - CardDavBackend $davBackend) { + CardDavBackend $davBackend, + ITimeFactory $timeFactory) { $this->appName = Application::APP_ID; $this->socialProvider = $socialProvider; $this->manager = $manager; @@ -73,6 +77,7 @@ class SocialApiService { $this->l10n = $l10n; $this->urlGen = $urlGen; $this->davBackend = $davBackend; + $this->timeFactory = $timeFactory; } @@ -254,6 +259,33 @@ class SocialApiService { return $report; } + /** + * @NoAdminRequired + * + * sorts an array of address books + * + * @param {IAddressBook} a + * @param {IAddressBook} b + * + * @returns {bool} comparison by URI + */ + protected function sortAddressBooks(IAddressBook $a, IAddressBook $b) { + return strcmp($a->getURI(), $b->getURI()); + } + + /** + * @NoAdminRequired + * + * sorts an array of contacts + * + * @param {array} a + * @param {array} b + * + * @returns {bool} comparison by UID + */ + protected function sortContacts(array $a, array $b) { + return strcmp($a['UID'], $b['UID']); + } /** * @NoAdminRequired @@ -265,7 +297,7 @@ class SocialApiService { * * @returns {JSONResponse} JSONResponse with the list of changed and failed contacts */ - public function updateAddressbooks(string $network, string $userId) : JSONResponse { + public function updateAddressbooks(string $network, string $userId, string $offsetBook = null, string $offsetContact = null) : JSONResponse { // double check! $syncAllowedByAdmin = $this->config->getAppValue($this->appName, 'allowSocialSync', 'yes'); @@ -276,10 +308,12 @@ class SocialApiService { $delay = 1; $response = []; + $startTime = $this->timeFactory->getTime(); // get corresponding addressbook $this->registerAddressbooks($userId, $this->manager); $addressBooks = $this->manager->getUserAddressBooks(); + usort($addressBooks, [$this, 'sortAddressBooks']); // make sure the order stays the same in consecutive calls foreach ($addressBooks as $addressBook) { if ((is_null($addressBook) || @@ -290,18 +324,32 @@ class SocialApiService { continue; } + // in case this is a follow-up, jump to the last stopped address book + if (!is_null($offsetBook)) { + if ($addressBook->getURI() !== $offsetBook) { + continue; + } + $offsetBook = null; + } + // get contacts in that addressbook - $contacts = $addressBook->search('', ['UID'], ['types' => true]); - // TODO: can be optimized by: - // $contacts = $addressBook->search('', ['X-SOCIALPROFILE'], ['types' => true]); - // but see https://github.com/nextcloud/contacts/pull/1722#discussion_r463782429 - // and the referenced PR before activating this (index has to be re-created!) + if (Util::getVersion()[0] < 20) { + //TODO: remove this branch when dependency for contacts is min NCv20 (see info.xml) + $contacts = $addressBook->search('', ['UID'], ['types' => true]); + } else { + $contacts = $addressBook->search('', ['X-SOCIALPROFILE'], ['types' => true]); + } + usort($contacts, [$this, 'sortContacts']); // make sure the order stays the same in consecutive calls // update one contact after another foreach ($contacts as $contact) { - // delay to prevent rate limiting issues - // TODO: do we need to send an Http::STATUS_PROCESSING ? - sleep($delay); + // in case this is a follow-up, jump to the last stopped contact + if (!is_null($offsetContact)) { + if ($contact['UID'] !== $offsetContact) { + continue; + } + $offsetContact = null; + } try { $r = $this->updateContact($addressBook->getURI(), $contact['UID'], $network); @@ -309,6 +357,18 @@ class SocialApiService { } catch (Exception $e) { $response = $this->registerUpdateResult($response, $contact['FN'], '-1'); } + + // stop after 15sec (to be continued with next chunk) + if (($this->timeFactory->getTime() - $startTime) > 15) { + $response['stoppedAt'] = [ + 'addressBook' => $addressBook->getURI(), + 'contact' => $contact['UID'], + ]; + return new JSONResponse([$response], Http::STATUS_PARTIAL_CONTENT); + } + + // delay to prevent rate limiting issues + sleep($delay); } } return new JSONResponse([$response], Http::STATUS_OK); |