Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/api/backend-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ Booking safety
- не пересекается ли новая бронь с активной бронью;
- можно ли создать запись в транзакции.

Обновление брони должно идти через optimistic concurrency contract:
`docs/api/booking-concurrency.md`.

Команды

npm run prisma:generate — сгенерировать Prisma Client.
Expand Down
39 changes: 39 additions & 0 deletions docs/api/booking-concurrency.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Booking Concurrency

Этот документ фиксирует целевой HTTP contract для optimistic concurrency control.

## Проблема

Два клиента могут одновременно обновить одну бронь. Например, оба отправляют
`PATCH /bookings/{bookingId}` со статусом `cancelled`. Без версии записи второй
запрос может выглядеть успешным, хотя он работал со stale состоянием.

## Целевой contract

Booking responses должны возвращать `ETag`, построенный из версии записи.
Изменяющие запросы должны передавать текущий token в `If-Match`.

Пример:

```http
PATCH /bookings/booking-1
If-Match: "booking-1:7"
Content-Type: application/json

{ "status": "cancelled" }
```

Если версия совпала, сервис применяет обновление и возвращает новый `ETag`.
Если запись уже изменилась, сервис возвращает:

```http
HTTP/1.1 412 Precondition Failed
```

## Следующие изменения в коде

- добавить поле `version` в `booking.Booking`;
- инкрементировать `version` при каждом статусном изменении;
- вернуть `ETag` в `GET /bookings` и `PATCH /bookings/{bookingId}`;
- проверять `If-Match` перед отменой или переносом брони;
- покрыть тестом конфликт двух параллельных отмен одной брони.
16 changes: 16 additions & 0 deletions docs/openapi/metrix-bot-api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ paths:
summary: Update booking status.
parameters:
- $ref: '#/components/parameters/BookingId'
- $ref: '#/components/parameters/IfMatch'
requestBody:
required: true
content:
Expand All @@ -282,6 +283,8 @@ paths:
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'412':
$ref: '#/components/responses/PreconditionFailed'
/invoices:
post:
tags:
Expand Down Expand Up @@ -720,6 +723,13 @@ components:
required: true
schema:
type: string
IfMatch:
name: If-Match
in: header
required: false
description: Optimistic concurrency token from the current booking ETag.
schema:
type: string
LocationId:
name: locationId
in: path
Expand Down Expand Up @@ -775,6 +785,12 @@ components:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
PreconditionFailed:
description: If-Match does not match the current booking version.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
schemas:
HealthResponse:
type: object
Expand Down
Loading