Веб-запрос Davical Sync-Token

Я стараюсь не изобретать велосипед здесь...

Я нашел хорошую документацию по реализации синхронизации CalDav здесь

Согласно его веб-сайту, DaviCal совместим с rfc6578, начиная с версии 0.9.8 (см. здесь).

Поэтому я сначала отправляю свой запрос на получение токена синхронизации следующим образом:

PROPFIND http://my_cal_srv/user/calendar_path HTTP/1.1
Content-Type: application/xml; charset="utf-8"
    <?xml version="1.0" encoding="utf-8" ?>
      <d:propfind xmlns:d='DAV:'> 
        <d:prop>
          <d:displayname />
          <d:sync-token />
        </d:prop>
       </d:propfind>

Это возвращает данные, как и ожидалось:

<?xml version="1.0" encoding="utf-8" ?>
<multistatus xmlns="DAV:">
 <response>
  <href>/caldav.php/user/calendar_path/</href>
  <propstat>
   <prop>
    <displayname>My Calendar</displayname>
    <sync-token>data:,9</sync-token>
   </prop>
   <status>HTTP/1.1 200 OK</status>
  </propstat>
 </response>
</multistatus>

Пока все хорошо, у меня есть токен, это «данные: ,9». Итак, давайте просто попробуем получить изменения с 8, токен, который у меня был, когда я запрашивал сервер перед добавлением некоторого события.

REPORT http://my_cal_srv/user/calendar_path HTTP/1.1
Content-Type: application/xml; charset="utf-8"
<?xml version="1.0" encoding="utf-8" ?>
<d:sync-collection xmlns:d="DAV:">
  <d:sync-token>8</d:sync-token>
  <d:sync-level>1</d:sync-level>
  <d:prop>
    <d:getetag/>
  </d:prop>
</d:sync-collection>

Ответ:

<?xml version="1.0" encoding="utf-8" ?>
<multistatus xmlns="DAV:">
 <response>
  <href>/caldav.php/user/path/86166f9c-3e2e-4242-9a28-0f3bfb1dd67a-caldavsyncadapter.ics</href>
  <propstat>
   <prop>
    <getetag>"5ed2101b0c867e490dbd71d40c7071bb"</getetag>
   </prop>
   <status>HTTP/1.1 200 OK</status>
  </propstat>
 </response>
 <response>
  <href>/caldav.php/user/path/cb354fab-b41d-49ad-8a4f-8d68c9090ea0.ics</href>
  <propstat>
   <prop>
    <getetag>"334892703f4151024e9232eab9b515a7"</getetag>
   </prop>
   <status>HTTP/1.1 200 OK</status>
  </propstat>
 </response>
 <sync-token>data:,9</sync-token>
</multistatus>

После удаления записи (поэтому я получаю токен синхронизации 10 и все еще сравниваю, используя токен 8), я получаю следующий результат:

<?xml version="1.0" encoding="utf-8" ?>
<multistatus xmlns="DAV:">
 <response>
  <href>/caldav.php/user/cal_path/86166f9c-3e2e-4242-9a28-0f3bfb1dd67a-caldavsyncadapter.ics</href>
  <status>HTTP/1.1 404 Not Found</status>
 </response>
 <response>
  <href>/caldav.php/user/cal_path/cb354fab-b41d-49ad-8a4f-8d68c9090ea0.ics</href>
  <propstat>
   <prop>
    <getetag>"334892703f4151024e9232eab9b515a7"</getetag>
   </prop>
   <status>HTTP/1.1 200 OK</status>
  </propstat>
 </response>
 <sync-token>data:,10</sync-token>
</multistatus>

Так что я немного смущен здесь, поскольку я действительно не знаю, как интерпретировать эти результаты...

Может ли кто-нибудь объяснить мне, как извлечь отсюда информацию о синхронизации? Немного сложно определить типы изменений, потому что названия ICS неясны...

Заранее спасибо за помощь... И счастливого Рождества! С уважением, Н.


person neggenbe    schedule 22.12.2014    source источник


Ответы (2)


То, что вы получаете «data:,9», не означает, что вы можете запрашивать «data:,8» или,7 и т. д. Токены синхронизации непрозрачны и НЕ предоставляют вам систему управления версиями (вам нужно что-то вроде Расширения управления версиями DAV).

Токены синхронизации DAV — это простой метод оптимизации, не более того. Они полностью непрозрачны для клиента, и срок действия токенов синхронизации может истечь в любое время (и от него не требуется сохранять надгробия и тому подобное). Например, сервер, который не может хранить надгробные камни, может просто истечь срок действия токенов при запросах DELETE.

То, как вы используете токены синхронизации:

  1. чтобы выяснить, какие дочерние коллекции родительской коллекции необходимо повторно синхронизировать
  2. оптимизировать синхронизацию ресурсов в дочерней коллекции

1) Какие дочерние коллекции необходимо синхронизировать

Предположим, у вас есть коллекция календарей (например, my_cal_srv/user/), и вы выполняете PROPFIND Depth:1 для этой коллекции, запрашивая токены синхронизации дочерних коллекций. Если они больше не совпадают с кэшем ваших клиентов, вы знаете, что вам нужно выполнить синхронизацию только этих дочерних коллекций.

Примечание. НЕ используйте токен, полученный в результате этого запроса, для синхронизации дочерней коллекции (что вы и делаете выше). Возможно, он уже истек. В отчетах о синхронизации используйте только токены, полученные из отчетов о синхронизации!

2) Оптимизация синхронизации содержимого коллекции

Еще раз: sync-токены — это оптимизация, не более того. Вы всегда должны быть готовы получить ошибку предварительного условия (in)valid-sync-token (что означает, что срок действия токена истек) и выполнить полную повторную выборку содержимого коллекции! А затем сравните это (URL, ETag) с вашей кешированной версией, чтобы выяснить, в чем заключаются изменения. (по сути, все шаги, которые вам нужно сделать, если у вас есть сервер, который не поддерживает отчеты о синхронизации).

Если вы получите токен синхронизации в результатах отчета о синхронизации, вы сможете использовать его в следующем запросе синхронизации. Если сервер все еще имеет состояние, он просто даст вам изменения. Если срок действия токена истек, он выдаст вам ошибку токена синхронизации.

Примечание: Если это не очевидно - в самом первом запросе на синхронизацию вы не предоставляете (не можете) токен. Вы запускаете запрос без токена и возвращаете все содержимое. Вы делаете то же самое снова, если сервер отправляет вам ошибку (in)valid-sync-token.

person hnh    schedule 31.12.2014
comment
Здесь все работает нормально. Обратите внимание, что для DaviCal оказывается, что если срок действия токена истек, сервер автоматически возвращает ВСЕ события в запросе. Я тестировал запрос с любым случайным ключом, и я никогда не получал ответ об ошибке, но, глядя на содержимое, он всегда возвращает ВСЕ события, расположенные на сервере. - person neggenbe; 18.06.2015
comment
Серьезная ошибка в DaviCal. Как клиент может выяснить, какие ресурсы были удалены по истечении срока действия токена? Для клиента это будет выглядеть так, как будто токен в порядке, и он обработает результаты как набор изменений (нет индикатора того, что ответ содержит все). - person hnh; 18.06.2015
comment
1) Исправить ошибку в DaviCal, 2.1) Обнаружить DaviCal через заголовок сервера и отключить отчеты о синхронизации в вашем клиенте, или 2.2) [хромой] время от времени запускать полный PROPFIND для обнаружения удалений. - person hnh; 18.06.2015
comment
Как насчет того, чтобы учесть, что возвращаемые элементы являются фактическим состоянием сервера. Поэтому мне нужно обнаруживать локальные коллизии для событий, которые существуют локально, но НЕ существуют на сервере. Для тех коллизий 2 варианта: 1. локальная версия была изменена ДО последней операции синхронизации => УДАЛИТЬ ЛОКАЛЬНО; 2. локальная версия была изменена ПОСЛЕ последней синхронизации => коллизия, при которой DELETE проигрывает => перезагрузка на сервер. Это не 100%, но соответствует стандартной процедуре коллизии, которую DELETE всегда проигрывает в случае сомнения. - person neggenbe; 18.06.2015
comment
Вариант 1 будет наиболее распространенным, и вы будете постоянно терять данные. Помните, что сервер возвращает изменения только в том случае, если токен действителен. Что чаще всего так и есть (если бы это было не так, вы могли бы в первую очередь использовать обычный PROPFIND, поскольку оптимизация не сработала бы). Если у вас есть 1000 событий в вашей БД, ваш токен действителен и 1 событие было изменено. Вы бы удалили оставшиеся 999. - person hnh; 18.06.2015
comment
Извините, я должен уточнить: локально я сохраняю отметку времени изменения, а также отметку времени последней синхронизации. Это позволяет мне обнаруживать столкновения. Если действительно все мои 1000 элементов были синхронизированы при last-sync и они исчезли на сервере => действительно, я удалю 999 из них. Однако, если бы все они были изменены ПОСЛЕ последней синхронизации, я бы ЗАГРУЗИЛ 999 элементов (поскольку они, скорее всего, были созданы локально). - person neggenbe; 18.06.2015
comment
999 элементов на самом деле не исчезли с сервера. В отчете о синхронизации сообщается об изменениях на стороне сервера только при наличии действительного токена. Пожалуйста, внимательно перечитайте то, что было написано, и, возможно, просто попробуйте. Если вам всегда нужны все записи, просто используйте propfind (или отчет о синхронизации без токена, что по сути то же самое) - person hnh; 18.06.2015
comment
Хорошо, понял - нет способа определить, является ли отчет об изменениях списком измененных событий ИЛИ полным списком .... Так что действительно, здесь это важно! Спасибо за объяснение! - person neggenbe; 18.06.2015

Вы делаете не правильный запрос. В вашем запросе у вас есть:

<d:sync-token>8</d:sync-token>

Но это должно быть:

<d:sync-token>data:,8</d:sync-token>

Кроме того, первый ответ, который вы получаете, говорит вам, что:

These resources have been changed or newly created:
/caldav.php/user/path/86166f9c-3e2e-4242-9a28-0f3bfb1dd67a-caldavsyncadapter.ics
/caldav.php/user/path/cb354fab-b41d-49ad-8a4f-8d68c9090ea0.ics

Второй ответ говорит вам:

This resource has been changed or newly created:
/caldav.php/user/cal_path/cb354fab-b41d-49ad-8a4f-8d68c9090ea0.ics

This resource has been deleted:
/caldav.php/user/cal_path/86166f9c-3e2e-4242-9a28-0f3bfb1dd67a-caldavsyncadapter.ics
person Evert    schedule 23.12.2014
comment
Ладно, покопаемся в этом. Таким образом, это означает, что нужно искать тег состояния: Для добавленных/обновленных записей я получу статус 200 ‹status›HTTP/1.1 200 OK‹/status› Для удаленных записей я получу статус 400 ‹status›HTTP /1.1 404 Not Found‹/status› Вот как вы интерпретируете результаты? - person neggenbe; 11.06.2015
comment
Да, в значительной степени. В спецификации тоже все есть. - person Evert; 18.06.2015