Убавить доступный баланс, прибавить заблокированный баланс. (создание ордера) - это две разные операции, вклиниться в которые запрос другого юзера не имеет права (иначе исполнится только половина запроса)
Вот как создается ордер:
1. Проверка: залочен ли пользователь для вывода?
2. Если не залочен - блок пользователя для создания/удаления ордеров
3. Сверить баланс пользователя с историей торговли и историей ввода/вывода
4. Если все нормально, обновить таблицу балансов
5. Если баланс обновился нормально, обновить таблицу ордеров.
6. Снять блок с пользователы для постановки/отмены ордеров
7. Еще раз сверить баланс пользователя с историей торговли и историей ввода/вывода
https://github.com/3s3s/opentrade/blob/master/server/modules/users/orders.js#L305
Убавить заблокированный баланс, прибавить доступный для одного юзера и сделать то же самого для другого. (исполнение ордера) - это уже 4 операции, опять таки - попадание асинхронного запроса другого юзера между ними приведет к непоправимой потере информации в середине цепочки.
Как эти проблемы решаются?
Вот как проходит исполнение ордера
1. Выбрать два пересекающихся ордера из стаканов
2. Заблокировать эти два ордера от изменений из других мест.
3. Проверить: заблокированы ли авторы ордеров для постановки/отмены ордеров.
4. Если не заблокированы, то заблокировать. Если хоть один заблокирован, то выйти из процедуры.
5. Обновить таблицу ордеров
6. Если таблица ордеров обновилась успешно, то разблокировать пользователей для постановки/отмены ордеров
7. Разблокировать ордера (если от них что-то осталось) для изменений
8. Обновить балансы пользователей и обновить таблицу истории.
В версии которая на гитхабе порядок немного другой
https://github.com/3s3s/opentrade/blob/master/server/modules/users/orders.js#L441Там пункт 8 стоит перед пунктами 6 и 7:
1. Выбрать два пересекающихся ордера из стаканов
2. Заблокировать эти два ордера от изменений из других мест.
3. Проверить: заблокированы ли авторы ордеров для постановки/отмены ордеров.
4. Если не заблокированы, то заблокировать. Если хоть один заблокирован, то выйти из процедуры.
5. Обновить таблицу ордеров
6. Обновить балансы пользователей и обновить таблицу истории.
7. Если таблица ордеров обновилась успешно, то разблокировать пользователей для постановки/отмены ордеров
8. Разблокировать ордера (если от них что-то осталось) для изменений
Так конечно более логично, но намного медленней в работе. Я так посчитал, что не обязательно ждать обновления балансов пользователей и истории. Если обновления пройдут с ошибками, то ошибка будет в пользу биржи, а не в пользу юзеров. Если юзеры не заметят ошибку - значит она для них не критична. Если заметят - значит создадут тикет и я вручную все проверю )