WebAPI - защита от дублирования - ваш выбор
От: Shmj Ниоткуда  
Дата: 31.08.22 18:58
Оценка:
Допустим, вызываем метод и он создает новый пункт заказа. Хотелось бы чтобы при n вызовах метода добавлялся только 1 пункт заказа (на случай повторных запросов при ошибке сетевой).

Варианты:

1. GUID.
2. Какая-нибудь метка времени + рандомное число, типа 220831215622121 — дата и время включая миллисекунды — уже тип int не вмещает, т.е. long. Ну и могут быть проблемы все-же, если запросы частые (что можно разрулить добавлением еще 3-5 разрядов рандомного числа).
3. Можно передавать ID пункта заказа, т.е. зная ID предыдущего делать инкремент.

Что еще?
Re: WebAPI - защита от дублирования - ваш выбор
От: Baiker  
Дата: 31.08.22 19:22
Оценка: -1 :))) :)))
Здравствуйте, Shmj, Вы писали:

S>Допустим, вызываем метод и он создает новый пункт заказа. Хотелось бы чтобы при n вызовах метода добавлялся только 1 пункт заказа (на случай повторных запросов при ошибке сетевой).


Откуда вообще взяться повторному запросу? Если в веб-функцию пришёл запрос, значит сервер уже получил полные данные и никаких "ошибке сетевой" там нет.
Ну и на всякий, поменьше юзать всякое г-но типа JS.
Re: WebAPI - защита от дублирования - ваш выбор
От: bnk СССР http://unmanagedvisio.com/
Дата: 31.08.22 19:35
Оценка: +1
Здравствуйте, Shmj, Вы писали:

S>Допустим, вызываем метод и он создает новый пункт заказа. Хотелось бы чтобы при n вызовах метода добавлялся только 1 пункт заказа (на случай повторных запросов при ошибке сетевой).


S>Варианты:


Я бы взял GUID конечно, если никаких специальных требований нет, зачем изобретать велосипед
Re: WebAPI - защита от дублирования - ваш выбор
От: samius Япония http://sams-tricks.blogspot.com
Дата: 31.08.22 20:38
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Варианты:


S>1. GUID.

S>2. Какая-нибудь метка времени + рандомное число, типа 220831215622121 — дата и время включая миллисекунды — уже тип int не вмещает, т.е. long. Ну и могут быть проблемы все-же, если запросы частые (что можно разрулить добавлением еще 3-5 разрядов рандомного числа).
S>3. Можно передавать ID пункта заказа, т.е. зная ID предыдущего делать инкремент.

S>Что еще?

Помечать состояние списка заказов номером, хэшем (fingerprint, ETag). По сути как коммит в GIT/оптимистическая блокировка. Это более общее решение, годится не только лишь для создания заказа, а вообще для работы со списком сущностей (создание, удаление, модификация)
Re[2]: WebAPI - защита от дублирования - ваш выбор
От: samius Япония http://sams-tricks.blogspot.com
Дата: 31.08.22 20:40
Оценка: 1 (1) +1
Здравствуйте, Baiker, Вы писали:

B>Откуда вообще взяться повторному запросу?

Ровно оттуда же, откуда возьмется первый запрос. Его отправит клиент, не получивший ответ на первый запрос.
Re[2]: WebAPI - защита от дублирования - ваш выбор
От: fmiracle  
Дата: 31.08.22 20:49
Оценка: 1 (1) +2
Здравствуйте, Baiker, Вы писали:

B>Откуда вообще взяться повторному запросу? Если в веб-функцию пришёл запрос, значит сервер уже получил полные данные и никаких "ошибке сетевой" там нет.


Сервер-то получил, но вот клиент может ответа от сервера не получить и получить разрыв соединения или таймаут и не знать — то ли это было до того как данные ушли на сервер, то ли уже после, и попробовать повторить операцию.
Re: WebAPI - защита от дублирования - ваш выбор
От: fmiracle  
Дата: 31.08.22 20:57
Оценка: 6 (1) +4
Здравствуйте, Shmj, Вы писали:

S>Допустим, вызываем метод и он создает новый пункт заказа. Хотелось бы чтобы при n вызовах метода добавлялся только 1 пункт заказа (на случай повторных запросов при ошибке сетевой).


Это называется идемпотентные операции, подходы к тому то что тебе нужно ищи по словам "ключ идемпотентности"

S>Варианты:

S>1. GUID.

Да

S>2. Какая-нибудь метка времени + рандомное число, типа 220831215622121 — дата и время включая миллисекунды — уже тип int не вмещает, т.е. long. Ну и могут быть проблемы все-же, если запросы частые (что можно разрулить добавлением еще 3-5 разрядов рандомного числа).


Это создание "как бы guid" вручную. Если есть возможность просто сгенерировать guid — то зачем оно?

S>3. Можно передавать ID пункта заказа, т.е. зная ID предыдущего делать инкремент.


Это один из вариантов построения ключа идемпотентности из самих данных. Другой вариант — вычислять от них хэш. Могут быть свои плюсы в подходе, но как по мне это более сложное и хрупкое решение, чем синтетический ключ наподобие гуида. Надо очень обдуманно выбирать. Но guid тоже не решает волшебно всех проблем, надо применять осмысленно.
Отредактировано 01.09.2022 6:52 fmiracle . Предыдущая версия .
Re: WebAPI - защита от дублирования - ваш выбор
От: DiPaolo Россия  
Дата: 01.09.22 01:37
Оценка: 93 (2) +1
S>1. GUID.
S>2. Какая-нибудь метка времени + рандомное число, типа 220831215622121 — дата и время включая миллисекунды — уже тип int не вмещает, т.е. long. Ну и могут быть проблемы все-же, если запросы частые (что можно разрулить добавлением еще 3-5 разрядов рандомного числа).
S>3. Можно передавать ID пункта заказа, т.е. зная ID предыдущего делать инкремент.

Зависит от требований системы. Иногда имеет смысл использовать все три способа. Подробнее описано тут https://stripe.com/blog/idempotency: первый пункт — раздел Guaranteeing “exactly once” semantics, второй и третий — Being a good distributed citizen.
Патриот здравого смысла
Отредактировано 01.09.2022 5:26 DiPaolo . Предыдущая версия .
Re[2]: WebAPI - защита от дублирования - ваш выбор
От: Shmj Ниоткуда  
Дата: 01.09.22 01:40
Оценка: :)))
Здравствуйте, fmiracle, Вы писали:

S>>2. Какая-нибудь метка времени + рандомное число, типа 220831215622121 — дата и время включая миллисекунды — уже тип int не вмещает, т.е. long. Ну и могут быть проблемы все-же, если запросы частые (что можно разрулить добавлением еще 3-5 разрядов рандомного числа).


F>Это создание "как бы guid" вручную. Если есть возможность просто сгенерировать guid — то зачем оно?


Потому что Guid монструозно и уродливо выглядит.
Re[3]: WebAPI - защита от дублирования - ваш выбор
От: DiPaolo Россия  
Дата: 01.09.22 02:13
Оценка:
S>Потому что Guid монструозно и уродливо выглядит.

Так тебе ж его не глазами читать — положил в базу, оно там лежит себе и периодически используется, и все.
Патриот здравого смысла
Re[4]: WebAPI - защита от дублирования - ваш выбор
От: Shmj Ниоткуда  
Дата: 01.09.22 06:19
Оценка:
Здравствуйте, DiPaolo, Вы писали:

DP>Так тебе ж его не глазами читать — положил в базу, оно там лежит себе и периодически используется, и все.


long — 8 байт, GUID — 16 байт.
Re: WebAPI - защита от дублирования - ваш выбор
От: Ночной Смотрящий Россия  
Дата: 01.09.22 08:54
Оценка: +2
Здравствуйте, Shmj, Вы писали:

S>1. GUID.

S>2. Какая-нибудь метка времени + рандомное число, типа 220831215622121 — дата и время включая миллисекунды — уже тип int не вмещает, т.е. long. Ну и могут быть проблемы все-же, если запросы частые (что можно разрулить добавлением еще 3-5 разрядов рандомного числа).
S>3. Можно передавать ID пункта заказа, т.е. зная ID предыдущего делать инкремент.
S>Что еще?

0. Сделать метод идемпотентным (грубо говоря, заменить POST на PUT)
Идея использовать для идентификатора семантически значимые поля приведет к тому, что в каждом конкретном случае тебе придется изобретать велосипед заново. Поэтому лучше синтетический ключ реквеста, формируемый автоматично в клиенте и передаваемый, с учетом ретраев, в хидере на сервер. Но вариант 0 лучше.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[2]: WebAPI - защита от дублирования - ваш выбор
От: Ночной Смотрящий Россия  
Дата: 01.09.22 08:55
Оценка:
Здравствуйте, bnk, Вы писали:

bnk>Я бы взял GUID конечно, если никаких специальных требований нет, зачем изобретать велосипед


Иногда важно восстатавливать исходную последовательность запросов (но, видимо, не в данном случае). Тогда нужен монотонно возрастающий ID, GUID не прокатит.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[3]: WebAPI - защита от дублирования - ваш выбор
От: Ночной Смотрящий Россия  
Дата: 01.09.22 08:58
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Потому что Guid монструозно и уродливо выглядит.


Зачем тебе его смотреть, это ж не correlationid, он только системе нужен. Но если хочешь немонструозно — можешь использовать cuid.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[2]: WebAPI - защита от дублирования - ваш выбор
От: Shmj Ниоткуда  
Дата: 01.09.22 09:10
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>Здравствуйте, Shmj, Вы писали:


S>>1. GUID.

S>>2. Какая-нибудь метка времени + рандомное число, типа 220831215622121 — дата и время включая миллисекунды — уже тип int не вмещает, т.е. long. Ну и могут быть проблемы все-же, если запросы частые (что можно разрулить добавлением еще 3-5 разрядов рандомного числа).
S>>3. Можно передавать ID пункта заказа, т.е. зная ID предыдущего делать инкремент.
S>>Что еще?

НС>0. Сделать метод идемпотентным (грубо говоря, заменить POST на PUT)


Как, если это пункт заказа? Может быть два одинаковых пункта заказа. Как отличить так и захотел клиент или же это ошибка из-за повторной отправки запроса?
Re[4]: WebAPI - защита от дублирования - ваш выбор
От: Shmj Ниоткуда  
Дата: 01.09.22 09:21
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>Зачем тебе его смотреть, это ж не correlationid, он только системе нужен. Но если хочешь немонструозно — можешь использовать cuid.


Ну еще зачем 16 байт, если и 8 хватит более чем.
Re[5]: WebAPI - защита от дублирования - ваш выбор
От: DiPaolo Россия  
Дата: 01.09.22 10:21
Оценка: +1
S>long — 8 байт, GUID — 16 байт.

Это не то место, где имеет смысл экономить. Грубо говоря, это 8 Мб лишних данных на миллион записей. Ну это ни о чем.
Патриот здравого смысла
Re[5]: WebAPI - защита от дублирования - ваш выбор
От: Ночной Смотрящий Россия  
Дата: 01.09.22 10:29
Оценка:
Здравствуйте, Shmj, Вы писали:

НС>>Зачем тебе его смотреть, это ж не correlationid, он только системе нужен. Но если хочешь немонструозно — можешь использовать cuid.

S>Ну еще зачем 16 байт, если и 8 хватит более чем.

cuid slug — от 7 до 10 байт, внутри счетчик, все как ты хочешь.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[3]: WebAPI - защита от дублирования - ваш выбор
От: Ночной Смотрящий Россия  
Дата: 01.09.22 10:29
Оценка: 5 (1)
Здравствуйте, Shmj, Вы писали:

НС>>0. Сделать метод идемпотентным (грубо говоря, заменить POST на PUT)

S>Как, если это пункт заказа?

Так. Id пункта заказа генеришь на клиенте. При ретраях id меняться не будет.

S> Может быть два одинаковых пункта заказа. Как отличить так и захотел клиент или же это ошибка из-за повторной отправки запроса?


В коде клиента отличишь. При создании пункта генеришь новый id, при ретрае остается тот же самый.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re: WebAPI - защита от дублирования - ваш выбор
От: maxkar  
Дата: 01.09.22 11:57
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Допустим, вызываем метод и он создает новый пункт заказа.

Клиента контроллируете вы или нет? Если вы не контроллируете, то просто говорите, что идентификатор пункта заказа — уникальная (в рамках заказа) строка. Дальше пусть клиент решает.

S>2. Какая-нибудь метка времени + рандомное число, типа 220831215622121 — дата и время включая миллисекунды — уже тип int не вмещает, т.е. long. Ну и могут быть проблемы все-же, если запросы частые (что можно разрулить добавлением еще 3-5 разрядов рандомного числа).

Я в ряде случаев использую инкрементальный счетчик, инициализируемый текущим временем (миллисекунды). Т.е. первый объект имеет время x = currentTimestamp(), второй — x+1 и т.д. Но зависит от сценария, в ряде случаев (много вкладок браузера открыты одновременно после восстановления/перезапуска) такой подход не работает. Я иногда в тестах использую. "Частые запросы" далеко не всегда проблема. Если у вас один запущенный клиент, идентификаторы позиций являются локальными в рамках заказа, то вероятность накликать две позиции с разницей меньше миллисекунды очень мала.

S>Что еще?

Put на /order/{orderId}/items со _всеми_ позициями заказа. Т.е. просто переписывать все. Иногда работает, иногда нет. Так как у вас был третий вариант (на основе предыдущего пункта заказа) — скорее всего работает.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.