Пока она лежит в очереди, пришло еще с десяток задач с id = 1. Все кроме последней задачи протухли и обрабатывать их уже не нужно.
Я ровно об этом и писал. Если мы получили задачу с определенным ID заказа, то варианта развития событий всего два: мы либо обновляем индекс свежайшей информацией из БД, либо не делаем ничего, поскольку данные кто-то уже обновил и в индексе хранятся уже самые актуальные данные.
Похода в ES можно избежать небольшой оптимизацией — хранить в памяти словарь "ID заказа — последняя полученная из ES версия". В таком случае если версия новой задачи меньше, чем та, что есть у нас в памяти, то даже в ES стучаться не надо.
При сохранении объекта в БД с использованием оптимистической блокировки получаем его актуальную версию (та, что в update ... set Version = Version + 1 where Version = ...)
Эту версию передаем в "задаче"
Когда наступает время обработки, вычитываем из ES "индексированную" версию объекта и сравниваем с той, что пришла в задаче. Если версия из задачи меньше, то просто ничего не делаем
Если индексировать всё же надо, то вычитываем сущность из БД (или получаем из API) и обновляем ES-индекс с использованием version_type=external
Можно еше поковырять ThreadPool.RegisterWaitForSingleObject() — он как раз для таких случаев подходит и избавляет от возни с вычислением миллисекунд.
Ну а по коду вот что. Во-первых, в тех местах, где int используется в качестве "столько-то миллисекунд", замените его на человечий TimeSpan. Во-вторых, совсем правильно было бы написать метод, типа PerformPeriodicCallback(Action callback, TimeSpan interval, WaitHandle stopEvent).
Ради задачи, для решения которой (в виде MVP) за глаза хватит SQLite, притащили адовый ворох SaaS решений, потратили кучу времени на взаимное интегрирование всего барахла (без описания, конечно же, что, куда и с какими учетными данными за чем обращается), технично разложили грабли с денормализацией и дублированием данных, да помножили в своей этой Ноде все строки на картинки.
Можно конечно с кавычками, но это просто неудобно.
Фу таким быть. Это вот после таких "неудобно" приходится каждому новичку объяснять, что "в Date у нас дата, Customar_ID — это по опечатка оплошности, и хранится там не Customer.ID, а LegalEntity.ID" и т.д.
Очень сложно с БД, как мне кажется. Мы у себя обратно-несовместимые изменения схем выполняем в несколько этапов.
Почему обновление фронтов такое многомудрое? Почему нельзя выкинуть веб-сервер из ротации на балансировщике, спокойно его обновить-прогреть и вернуть обратно в балансировщик?
Почему такие строгие требования к "версионности" сервисов? Почему не разрешить версии сервиса M.N, ранее работавшей с сервисом версии P.K, общаться с версией сервиса P.K+1?
Как, например, следующий способ. Взять Statsify (порт Graphite под Windows), установить на требуемые сервера Statsify Agent, в statsify-agent.config перечислить, какие счётчики собирать, потом установить Grafana и наблюдать красивые графики. Плюс автоматом получаем историю, агрегирование данных и т.д.
«Правильнее» будет называть это не «изменением истории», а «решением, какая это история будет»: You are not «rewriting» history. You are deciding history.
Буду предельно банален: https://xkcd.com/927/
А как потом во всем проекте обновить версию зависимости?
То есть у вас такие сервисы, которые ни вовне не обращаются, ни запросы в БД не делают? Иначе все вот эти оптимизации практически сходят на нет.
Я ровно об этом и писал. Если мы получили задачу с определенным ID заказа, то варианта развития событий всего два: мы либо обновляем индекс свежайшей информацией из БД, либо не делаем ничего, поскольку данные кто-то уже обновил и в индексе хранятся уже самые актуальные данные.
Похода в ES можно избежать небольшой оптимизацией — хранить в памяти словарь "ID заказа — последняя полученная из ES версия". В таком случае если версия новой задачи меньше, чем та, что есть у нас в памяти, то даже в ES стучаться не надо.
Что-то или очень сложно, или я что-то упускаю.
update ... set Version = Version + 1 where Version = ...
)version_type=external
Можно еше поковырять
ThreadPool.RegisterWaitForSingleObject()
— он как раз для таких случаев подходит и избавляет от возни с вычислением миллисекунд.Ну а по коду вот что. Во-первых, в тех местах, где
int
используется в качестве "столько-то миллисекунд", замените его на человечийTimeSpan
. Во-вторых, совсем правильно было бы написать метод, типаPerformPeriodicCallback(Action callback, TimeSpan interval, WaitHandle stopEvent)
.Накликай мышкой себе девопса. Позор-то какой.
Каких, например?
Построить дедупликацию на CRC32 — это сильно!
Хипстеры на марше.
Ради задачи, для решения которой (в виде MVP) за глаза хватит SQLite, притащили адовый ворох SaaS решений, потратили кучу времени на взаимное интегрирование всего барахла (без описания, конечно же, что, куда и с какими учетными данными за чем обращается), технично разложили грабли с денормализацией и дублированием данных, да помножили в своей этой Ноде все строки на картинки.
Оглушительный успех, я считаю.
Вот сами руки написали, клянусь макаронным монстром!
Фу таким быть. Это вот после таких "неудобно" приходится каждому новичку объяснять, что "в Date у нас дата, Customar_ID — это по опечатка оплошности, и хранится там не Customer.ID, а LegalEntity.ID" и т.д.
Кинетесь ссылкой на почитать?
Очень сложно с БД, как мне кажется. Мы у себя обратно-несовместимые изменения схем выполняем в несколько этапов.
Почему обновление фронтов такое многомудрое? Почему нельзя выкинуть веб-сервер из ротации на балансировщике, спокойно его обновить-прогреть и вернуть обратно в балансировщик?
Почему такие строгие требования к "версионности" сервисов? Почему не разрешить версии сервиса M.N, ранее работавшей с сервисом версии P.K, общаться с версией сервиса P.K+1?
Что-то очень сложно.
Как, например, следующий способ. Взять Statsify (порт Graphite под Windows), установить на требуемые сервера Statsify Agent, в statsify-agent.config перечислить, какие счётчики собирать, потом установить Grafana и наблюдать красивые графики. Плюс автоматом получаем историю, агрегирование данных и т.д.
Очень переусложнено всё и перемешано.
Как минимум, нужно отдельно выделить лексер — тогда упростилось бы решительно всё, начиная от объектной модели и заканчивая логикой самого парсера.
А вообще — очень рекомендую вот эту статью: Pratt Parsers: Expression Parsing Made Easy.