|
10 | 10 |
|
11 | 11 | use OCP\AppFramework\Db\TTransactional; |
12 | 12 | use OCP\AppFramework\Http; |
| 13 | +use OCP\DB\Exception; |
13 | 14 | use OCP\Http\Client\IClient; |
14 | 15 | use OCP\Http\Client\IClientService; |
15 | 16 | use OCP\IConfig; |
@@ -89,15 +90,33 @@ public function syncRemoteAddressBook(string $url, string $userName, string $add |
89 | 90 | * @throws \Sabre\DAV\Exception\BadRequest |
90 | 91 | */ |
91 | 92 | public function ensureSystemAddressBookExists(string $principal, string $uri, array $properties): ?array { |
92 | | - return $this->atomic(function () use ($principal, $uri, $properties) { |
93 | | - $book = $this->backend->getAddressBooksByUri($principal, $uri); |
94 | | - if (!is_null($book)) { |
95 | | - return $book; |
| 93 | + try { |
| 94 | + return $this->atomic(function () use ($principal, $uri, $properties) { |
| 95 | + $book = $this->backend->getAddressBooksByUri($principal, $uri); |
| 96 | + if (!is_null($book)) { |
| 97 | + return $book; |
| 98 | + } |
| 99 | + $this->backend->createAddressBook($principal, $uri, $properties); |
| 100 | + |
| 101 | + return $this->backend->getAddressBooksByUri($principal, $uri); |
| 102 | + }, $this->dbConnection); |
| 103 | + } catch (Exception $e) { |
| 104 | + // READ COMMITTED doesn't prevent a nonrepeatable read above, so |
| 105 | + // two processes might create an address book here. Ignore our |
| 106 | + // failure and continue loading the entry written by the other process |
| 107 | + if ($e->getReason() !== Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) { |
| 108 | + throw $e; |
96 | 109 | } |
97 | | - $this->backend->createAddressBook($principal, $uri, $properties); |
98 | 110 |
|
99 | | - return $this->backend->getAddressBooksByUri($principal, $uri); |
100 | | - }, $this->dbConnection); |
| 111 | + // If this fails we might have hit a replication node that does not |
| 112 | + // have the row written in the other process. |
| 113 | + // TODO: find an elegant way to handle this |
| 114 | + $ab = $this->backend->getAddressBooksByUri($principal, $uri); |
| 115 | + if ($ab === null) { |
| 116 | + throw new Exception('Could not create system address book', $e->getCode(), $e); |
| 117 | + } |
| 118 | + return $ab; |
| 119 | + } |
101 | 120 | } |
102 | 121 |
|
103 | 122 | private function prepareUri(string $host, string $path): string { |
|
0 commit comments