Связь между сервисом прокатом бэкенды Сервиса Шеринга это отдельные се

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# Связь между сервисом и прокатом
Т.к. бэкенды Сервиса и Шеринга это отдельные сервисы, каждый бэкенд имеет свою независимую базу данных. Возникает проблема что список самокатов дублируется в каждой базе, и статусы самокатов могут различаться в каждом из сервисов, что может привести например к тому что пользователи и обслуживающий персонал могут ошибочно взять самокат в поездку и в обслуживание одновременно.
Во избежание таких ситуаций, необходим механизм синхронизации состояния самокатов между сервисами, который описан ниже.
## Описание механизма синхронизации
### Синхронное изменение статуса
"Источником правды" о статусе самоката является бэкенд Шеринга. При взятии самоката в обслуживание, бэкенд Сервиса делает http запрос к бэкенду Шеринга, который переводит самокат в необходимый статус. При невозможности такой операции (статус самоката изменился с момента последней синхронизации между бэкендами), бэкенд Сервиса запрещает операцию взятия самоката в обслуживания для пользователя и обновляет состояние самоката в своей базе.
### Асинхронные уведомления об изменениях статуса
Т.к. операция взятия в обслуживание создаёт несколько объектов в базе данных Сервиса, она обёрнута в транзакцию. При наступлении некоторых условий (нарушение констрейнтов базы данных) данная транзакция может быть прервана и база вернётся к первоначальному состоянию. Возникает ситуация, что статус самоката был обновлён в Шеринге, но не был обновлён в Сервисе. Во избежание таких ситуация, Сервис должен отправлять сообщение об отмене смены статуса, если транзакция откатилась.
После окончания сервисного обслуживания, самокат может быть возвращён на линию или переведён в состояние ожидания ремонта. В любом случае, Сервис посылает событие о смене статуса самоката, по которому бэкенд Шеринга решает что делать с самокатом - возвращать на линию в своей базе или оставлять статус самоката "в сервисе".
Бэкенд Шеринга также посылает события о любом изменении статуса самоката в своей базе, с помощью которых Сервис имеет возможность поддерживать свою версию состояний самокатов в актуальном состоянии.
Важная деталь реализации: все события о смене статусов должны посылаться только после того, как соответствующая транзакция в базе данных была закомминчена (on_commit хук в джанго).
### Переодическая синхронизация состояний
В дополнение к синхронизации статусов через события, бэкенд Шеринга должен переодически проверять что все самокаты помеченные как находящиеся в сервисном обслуживании действительно в нём находятся. Для этого в бэкенде Шеринга создаётся переодическая Celery задача, которая делает http запрос к бэкенду Сервиса и проверяет что все самокаты IN_SERVICE действительно находятся в сервисе с точки зрения базы данных Сервиса.
Похожий переодический процесс синхронизации необходим и в бэкенде Сервиса, на случай если какие-то сообщения от Шеринга не были доставлены по какой-то причине.
### Версионирование статусов самоката
Т.к. события о смене статусов посылаются асинхронно, возможны ситуации когда сообщения будут доставлены не в том порядке, в котором они были отправлены или по каким-то причинам не доставлены вообще.
Для того, чтобы иметь возможность определять такие ситуация, в каждый самокат добавляется поле с "версией" последнего изменения статуса. Каждая успешная операция изменения статуса внутри сервиса инкрементит этот поле. При отправке уведомления, версия статуса включается в сообщение. Сервис, который получает сообщение, должен проверять что версия статуса не меньше чем та, которая записана у него в базе.
Версия может только монотонно увеличваться, и никогда не может уменьшаться или оставаться прежней при успешной смене статуса.