Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
eventqueuemanager.php
1<?php
2
4
5use Bitrix\Calendar\Core;
22use Exception;
23
25{
26 public const CHECK_EVENTS_PERIOD = 300; // length in seconds
27 private const CHECK_ENTRY_LIMIT = 10;
28 private const SHIFT_DATE_RETRY_COUNT = 25;
29 private const MAX_RETRY_COUNT = 20;
30 private array $connectionList = [];
31
35 private Core\Mappers\Factory $mapperFactory;
36
40 public function __construct()
41 {
42 $this->mapperFactory = ServiceLocator::getInstance()->get('calendar.service.mappers.factory');
43 }
44
52 public static function checkEvents(): ?string
53 {
54 if (
55 !Loader::includeModule('calendar')
56 || !Loader::includeModule('dav')
57 )
58 {
59 return null;
60 }
61
63
64 $entriesDb = $qm::getEventListDb();
65 while ($queueItem = $entriesDb->Fetch())
66 {
67 $connection = $qm->getConnectionForQueueItem($queueItem);
68
69 $event = $qm->mapperFactory->getEvent()->getEntity((int)$queueItem['EVENT_ID']);
70 if (!$event)
71 {
72 continue;
73 }
74
75 $context = $qm->prepareEventContext(
76 [
77 'connection' => $connection,
78 'event' => $event,
79 'queueItem' => $queueItem,
80 ]
81 );
82
83 if ($event->getOwner() === null || $event->getOwner()->getId() === null)
84 {
85 $eventConnection = $context->getEventConnection();
86 if ($eventConnection !== null)
87 {
88 $qm->mapperFactory->getEventConnection()->update(
89 $eventConnection->setLastSyncStatus(Dictionary::SYNC_STATUS['success'])
90 );
91 }
92
93 continue;
94 }
95
96 $factory = FactoryBuilder::create($connection->getVendor()->getCode(), $connection, $context);
97 $syncManager = new VendorSynchronization($factory);
98 $result = null;
99
100 try
101 {
102 switch ($queueItem['SYNC_STATUS'])
103 {
104 case Dictionary::SYNC_STATUS['create']:
105 $result = $syncManager->createEvent($event, $context);
106 break;
107 case Dictionary::SYNC_STATUS['recreate']:
108 $result = $syncManager->deleteEvent($event, $context);
109 // TODO: create eventConnection with status "create"
110 $result = $syncManager->createEvent($event, $context);
111 break;
112 case Dictionary::SYNC_STATUS['update']:
113 $result = $syncManager->updateEvent($event, $context);
114 break;
115 case Dictionary::SYNC_STATUS['delete']:
116 $result = $syncManager->deleteEvent($event, $context);
117 break;
118 }
119 }
120 catch (Exception $e)
121 {
122 }
123
124 $eventLink = $qm->mapperFactory->getEventConnection()->getMap(
125 [
126 '=EVENT_ID' => $event->getId(),
127 '=CONNECTION_ID' => $factory->getConnection()->getId(),
128 ]
129 )->fetch();
130
131 if (!is_null($eventLink))
132 {
133 $retryCount = $eventLink->getRetryCount() + 1;
134 $currentNextSyncTry = $connection->getNextSyncTry();
135 if ($result && $result->isSuccess())
136 {
137 $resultData = $result->getData();
138
139 if (
140 is_array($resultData)
141 && (isset($resultData[$factory->getConnection()->getVendor()->getCode()])
142 && $resultData[$factory->getConnection()->getVendor()->getCode()]['status']
143 === Dictionary::SYNC_STATUS['success']
144 || ($resultData['status'] ?? null) === Dictionary::SYNC_STATUS['success'])
145 )
146 {
147 $eventLink->setLastSyncStatus(Dictionary::SYNC_STATUS['success']);
148 $retryCount = 0;
149 $currentNextSyncTry = null;
150 }
151 }
152
153 if (
154 $eventLink->getLastSyncStatus() !== Dictionary::SYNC_STATUS['success']
155 && $retryCount > self::MAX_RETRY_COUNT
156 )
157 {
158 $eventLink->setLastSyncStatus(Dictionary::SYNC_STATUS['failed']);
159 }
160
161 $eventLink->setRetryCount($retryCount);
162 $qm->mapperFactory->getEventConnection()->update($eventLink);
163 }
164 else
165 {
166 $retryCount = 0;
167 $currentNextSyncTry = null;
168 }
169
170 $connection->setNextSyncTry(
171 self::prepareNextSyncTry(
172 $currentNextSyncTry,
173 $retryCount
174 )
175 );
176 }
177
178 $qm->saveConnections();
179
180 return "\\Bitrix\\Calendar\\Sync\\Managers\\EventQueueManager::checkEvents();";
181 }
182
183 public static function createInstance(): EventQueueManager
184 {
185 return new self();
186 }
187
191 private static function getEventListDb()
192 {
193 global $DB;
194 $sqlQuery = "SELECT "
195 . " e.SECTION_ID,"
196 . " ec.ID as EVENT_CONNECTION_ID,"
197 . " ec.EVENT_ID,"
198 . " ec.ENTITY_TAG,"
199 . " ec.VENDOR_VERSION_ID,"
200 . " ec.CONNECTION_ID,"
201 . " ec.VENDOR_EVENT_ID,"
202 . " ec.VERSION,"
203 . " ec.SYNC_STATUS,"
204 . " ec.RETRY_COUNT,"
205 . " con.*"
206 . " FROM b_calendar_event e"
207 . " INNER JOIN b_calendar_event_connection ec ON ec.EVENT_ID = e.ID "
208 . " INNER JOIN b_calendar_section s ON s.ID = e.SECTION_ID "
209 . " INNER JOIN b_dav_connections con ON con.ID = ec.CONNECTION_ID "
210 . " INNER JOIN b_calendar_section_connection sc ON sc.SECTION_ID = e.SECTION_ID "
211 . " WHERE "
212 . " ec.SYNC_STATUS <> '" . Dictionary::SYNC_STATUS['success'] . "'"
213 . " and ec.SYNC_STATUS <> '" . Dictionary::SYNC_STATUS['failed'] . "'"
214 . " and s.ACTIVE = 'Y' and sc.ACTIVE = 'Y' and sc.CONNECTION_ID = con.ID"
215 . " and con.NEXT_SYNC_TRY <= NOW()"
216 . " ORDER BY ec.RETRY_COUNT ASC"
217 . " LIMIT " . self::CHECK_ENTRY_LIMIT;
218
219 return $DB->Query($sqlQuery);
220 }
221
222 private function getConnectionForQueueItem(array $queueItem): Connection
223 {
224 $connectionId = (int)$queueItem['CONNECTION_ID'];
225 if (!isset($this->connectionList[$connectionId]))
226 {
227 $this->connectionList[$connectionId] = (new BuilderConnectionFromArray($queueItem))->build();
228 }
229
230 return $this->connectionList[$connectionId];
231 }
232
233 private function prepareEventContext(array $params): EventContext
234 {
235 $queueItem = $params['queueItem'];
236
237 $context = new Context(
238 [
239 'connection' => $params['connection'],
240 ]
241 );
242
243 $eventLink = (new EventConnection())
244 ->setId($queueItem['EVENT_CONNECTION_ID'])
245 ->setEntityTag($queueItem['ENTITY_TAG'])
246 ->setVendorVersionId($queueItem['VENDOR_VERSION_ID'])
247 ->setRetryCount($queueItem['RETRY_COUNT'])
248 ->setLastSyncStatus($queueItem['SYNC_STATUS'])
249 ->setVendorEventId($queueItem['VENDOR_EVENT_ID'])
250 ->setData(json_decode($queueItem['DATA'] ?? ''))
251 ->setVersion((int)$queueItem['VERSION'])
252 ->setConnection($params['connection'])
253 ->setEvent($params['event']);
254
255 $sectionLink = $this->mapperFactory->getSectionConnection()->getMap(
256 [
257 '=SECTION_ID' => (int)$queueItem['SECTION_ID'],
258 '=CONNECTION_ID' => (int)$queueItem['CONNECTION_ID'],
259 ]
260 )->fetch();
261
262 $context = (new EventContext())->merge($context)->setEventConnection($eventLink)->setSectionConnection(
263 $sectionLink
264 );
265
266 return $context;
267 }
268
277 private static function prepareNextSyncTry(?Date $currentNextSyncTime, int $retryCount): Date
278 {
279 $nextSyncTime = new Date(new Type\DateTime());
280 if ($retryCount > self::SHIFT_DATE_RETRY_COUNT)
281 {
282 $nextSyncTime = $nextSyncTime->add('+1 day');
283 }
284
285 if (!is_null($currentNextSyncTime) && $currentNextSyncTime->getTimestamp() > $nextSyncTime->getTimestamp())
286 {
287 $nextSyncTime = $currentNextSyncTime;
288 }
289
290 return $nextSyncTime;
291 }
292
293 private function saveConnections()
294 {
295 foreach ($this->connectionList as $connectionId => $connection)
296 {
297 try
298 {
299 $this->mapperFactory->getConnection()->update($connection);
300 }
301 catch (Exception $e)
302 {
303 }
304 }
305 }
306}