Сколько хочу попробовать кип элайв или http/2 во внутренних коммуникациях между сервисами, но у нас балансировка на уровне DNS. У вас нет такой проблемы автоскелинга и балансировки запросов?
Писать балансировку на клиенте не хочется, а ставить лоад балансер чтобы он держал конекшены и балансил все девопс пока не хочет…
'use strict';
var isOdd = require('is-odd');
module.exports = function isEven(i) {
return !isOdd(i);
};
Который состоит из
'use strict';
const isNumber = require('is-number');
module.exports = function isOdd(value) {
const n = Math.abs(value);
if (!isNumber(n)) {
throw new TypeError('expected a number');
}
if (!Number.isInteger(n)) {
throw new Error('expected an integer');
}
if (!Number.isSafeInteger(n)) {
throw new Error('value exceeds maximum safe integer');
}
return (n % 2) === 1;
};
Который состоит из
'use strict';
module.exports = function(num) {
if (typeof num === 'number') {
return num - num === 0;
}
if (typeof num === 'string' && num.trim() !== '') {
return Number.isFinite ? Number.isFinite(+num) : isFinite(+num);
}
return false;
};
Где-то мир свернул не туда…
Насчет безруких разработчиков. Тут проблема не в безруких. Проблема в разных. С разным бэкграундом, целями, возможностями, хотелками, опытом и т.д. И вот тут та свобода и «простота» которую дает JS выходит боком.
От части да. Именно поэтому в пхп начали появляться Type declarations.
Но добавьте к этому еще то что весь хайп зарождался фронтендерами которые теперь могли писать бэкенд. Писали как умели. Добавьте к этом коллбэки и промисы и вообще асинхронную модель. Никаких тебе паттернов написания бэкенд сервисов. Синглтоны наше все. Тесты? О да. Давайте вначале нахреначим кода нетестируемого, а потом придумает JEST который магией поможет протестировать это все.
Если в в любом статическом языке вы 100 раз будете думать использовать ли рефлекшен, то услышать от JS разработчика «давай метапрограммирование здесь заюзеам, классная штука, я тут на конференции увидел» это нормально. Он даже не понимает какие последствия всего этого могут быть. Не хватает того что язык динамический и ты можешь себе выстрелить в голову через ногу, есть люди которые не боятся, как бы это сказать, возвести эту проблему в степень.
Да, согласен, поднять серверок за 2 минуты это круто. Запилить крад апи прямо в базу с монгуси, еще 5 минут. И если это изначально маленький проектик, то нет проблем. Но для больших проектов надо понимать, что за все придется платить.
И это я еще не говорю про то что многие не понимают разницу между CPU bound/IO bound. А если начинают понимать, начинают пизать решения типа форков, от которых меня тошнит.
Многие не доходили до проблема когда GC тупо съедает все CPU потому что такое количество инлайновых обьектов и стрингов создается что он не успевает очищать память…
Рефактор без компилятора, и даже с тестами — то еще удовольствие.
Мы вот нахавались, начали внедрять Type Script с надеждой что хоть часть проблем он уберет. С оставшимися научимся жить.
Проблема в том что многие пишут на JS скриптики или что-то простенькое, и не всегда доходят до проблем реальных приложений с нагрузкой и большой кодовой базой. Вот они будут хвалить JS.
Люди с опытом уже не так сильно будут радоваться тому что вебсервер поднять на експрессе с монго в 100 раз быстрее чем на жаве или дот нет, если знают что им нужно будет в будущем это поддерживать. Потому-что понимают во что это позже выльется. А если написать, и через 2-3 годика свалить, то норм. Уже не твои проблемы. Уже другому придется объяснять почему переименовать филд в проекте это месяц работы…
Но опять же, для POC или простых проектов, особенно IO Bound нода свою работу делает.
P.S.
А еще я всегда ржу что винда на пентиуме быстрее поднимается чем билд и приложение на ноде с +100500 зависимостями =)
Стоит. На нем все еще пилят вебсервера. Но, если это с нуля пописать годик-два, это одно. А если вы придете в проект где сервисы на ноде прошли через руки 10-20 человек, да поможет вам бог в поддержке этого чуда. Вы будете молиться на каждом деплое и станете верующим. Возможно даже уйдете в монастырь =)
Вы будете мечтать о компиляторе каждый раз когда будет прилетать эксепшен или блокер из-за самых тупых вещей. Когда весь проект написан на объектах, без нормальных моделей данных, вы будет открывать любую функцию, смотреть на параметры типа options, и гадать — а что там внутри?
Есть огромная разница между людьми которые пишут POC на JS и прыгают со стартапа в стартап и никогда не доходят до момента когда простенький POC вырос в гиганта и теперь кому-то с этим жить.
Есть и плюсы. Легаси еще лет на 10 как минимум хватит что-бы поддерживать и переписывать на тайп скрипт или другие языки. А это рабочие места и зряплата Ж)
Когда проект, количество кода и разработчиков растет, с чистым JS работать невозможно. Но быстрый старт — это да… главное потом выжить.
А вы знаете что уже сегодня есть поколение разработчиков не видавших никогда колбэк хела уровней так на 10 со всякими вотерфолами? А потом еще обернутыми в промисы =))
Как-то не убедили без цифр. Ну хотя бы RPs, mem/cpu usage до и после.
HTTP/2 не обязывает использовать gRPC
Даже до HTTP/2 можно keep-alive попробовать
Генерить типы для разных языков можно и со свагера
Единственное что подкупает это то, что сериализация должна быть быстрей. Мы же любим все быстрое Ж) Но и тут я не уверен что это правило работает для всех платформ. (https://medium.com/@onufrienkos/benchmarking-performance-grpc-vs-rest-on-node-js-bf766127f170)
И что больше всего пугает это то, что старый ламповый RPC не очень то и популярен в связи с проблемами которые он приносит с собой. Почему же так хайпят на gRPC?
Понимать как работает движок полезно и интересно. Главное что бы человек понимал что конкретно этот пример является классическим premature optimization. Потому как я уверен что в продакшене вместо 1000^3 итераций:
for(var i = 0; i < 1000 * 1000 * 1000; i++)
даже если их будет 100, время потраченное на оптимизацию не окупится в ближайшие лет 10 =)
А еще бывает весело когда кто-то вешается на 404-ю ошибку что бы удалить у себя что-то связанное с объектом (ну потому что 404, значит объект был удален). А потом выясняется что что кто-то баг засунул в роутинг или настройки лоадбалансера/прокси или еще чего. Вот и получили блокер на ровном месте. Поэтому мы всегда проверяем респонс, даже когда это 404-я.
Мне кажется все к этому приходят. Более того, часто и одного уровня ошибки не хватает, потому что могут быть разные причины приводящие к одной ошибке, и нужно реагировать по разному.
Поэтому можно неделю потратить на обсуждение формата ошибок с коллегами споря о кошерности того или иного решения.
Я обычно советую не изобретать велосипед, а посмотреть что делают гиганты и взять что то среднее.
Например фейсбук использует
{
"error": {
"message": "Message describing the error",
"type": "OAuthException",
"code": 190,
"error_subcode": 460,
"error_user_title": "A title",
"error_user_msg": "A message",
"fbtrace_id": "EJplcsCHuLu"
}
}
Конкурентные запросы упрутся в транзакции, кто первый запрос бросил — того и тапки.
Возможно мне нужно было уточнить что большинство мутаций у нас делается асинхронно.
Зачем тут кафка — непонятно.
Ну у нас такие доводы в пользу кафки (сейчас используем раббит и в основном без транзакций, потому что из еще не было в монге когда это разрабатывалось):
1. Пользователи насилуют систему как хотят и нам надоело иметь дело с параллельным процессингом или вообще обратным порядком команд. Например когда они делают Update -> Delete. На самом деле они могут делать много операций и нам это делает проблемы. С раббитом мы теряем order потому что скейлинг.
2. Кафка обеспечит нам partial order (партишенинг кафки по агрегату)
3. Опять же из-за партишенинга, у нас есть возможность использовать locality data patterns и работать с агрегатом при помощи load data -> mutate -> store, и не бояться что в соседнем воркере хэндлер тоже что-то сделал с этими данными.
4. Ну и в связке с DDD хотим топики и т.д. в любом случае.
5. В этом случае в принципе транзакции нам нужны только для «все или ничего с ролбэками». Боюсь что без этого транзакции убьют перформанс на нет когда все и вся будет ритраиться из-за конфликтов.
В принципе партишенинг можно и раббитом сделать, но там нет автоматического ребаланса консюмеров, а ручками мы это делать не хотим.
В реале речь идет о бронировании, не лотах. Так же бизнес b2b и каждая проблема с неправильными данными грозит потерей клиента. Например если вдруг 2 человека забронировали вещь, придется одному из них отказать, и возместить. Но с монги уйти не можем.
Не уверен что всех этих проблем можно избежать полагаясь только на транзакции. Тем более придется разбираться очень хорошо с изоляциями транзакций (например Serializable как я понимаю монго не поддерживает). Всякие фантомные ридс и т.д. Я то в конце разберусь, а вот остальные люди в компании — не уверен что все разберутся.
Приходилось ли кому натягивать сову на глобус попробовать имплементировать DDD для задач где есть работа с календарем?
Например есть вещь и есть календарь у этой вещи. Любой человек может попросить попользоваться этой вещью на определенное время. Если запрос удовлетворен, то это вещь принадлежит определенному человеку на определенный период. Если нет, то в календаре состояние этой вещи на определенные даты отображается со статусом «pending» например. Статусы могут быть разными. Вещь можно передавать другому человеку, отменять и т.д. Может быт несколько запросов от разных человек на разные даты и они будут отображаться в календаре.
Можно смотреть на это вещи и из состояние. Допустим есть у нас:
Item {
id
title
…
}
state block {
id
startDate
endDate
itemId
status [available, pending, reserved, unavailable]
userId
}
У нас вот задача есть похожая но на порядок сложнее (для примера я ооочень сильно упростил), и мы вот думаем как впихнуть это в агрегат. И что-то сомневаемся…
1. Много конкурентных запросов и команд для определенной вещи от разных людей, апи и скедулеров которые в конце концов манипулируют стейтом. Создают, меняют даты, статус, овнеров и т.д.
2. Стейты могут накладывать друг на друга с разными датами, статусами и т.д по определенным правилам.
3. Нужно обеспечить целостность данных. Например 2 запроса одновременно могут увидеть что вещь свободна (!reserved, unavailable), и попытаяются зарезервировать его. В это время кто то может вручную заассайнить вещь на эти же даты на другого человека. И в это же время какой нибудь скедулер отменяет стейт в том же диапазоне дат потому что статус pending ничего не решает.
Вот что мы думаем.
1. Стейт блок как агрегат. Но, пользователи работают с датами календаря и вещами. Они не видят и не знают что это имплементировано в базе стейтами с айдишниками. Айдишники это скорее для девелоперов просто что бы оперировать данными в базе. Пользователи могут выбрать вещь и отменить пользование в определенных датах, а внутри уже наш код знает как обрезать стейты, делаить их или мержить. Их может быть несколько эти стейт блоков. Не вариант вобщем.
2. Item это агрегат рут. И вся работа со стейтами (календарем) будет идти через него. И так как он должен быть под транзакцией и никакого конкурентного доступа к нему не должно быть на запись по определению агрегата (если я не ошибаюсь), мы можем загрузить в память календарь этого агрегата по itemId, делать с ним что хотим, со всеми этими стейтами, пока остальные ждут, и потом сохранить. Чтобы не было конкурентного доступа на мутации будет кафка с партишенами по айтему ну и/или оптимистик лок и/или транзакции. НО — если человек хочет взять вещь на след неделе, на 4 дня, то его запрос будет ждать пока агрегат освободиться, потому что кто то зарезервировал пользование на сегодня и идет обработка. Ну то есть мы убиваем конкаренси тут конкретно, а нам она нужна.
На самом деле реальная бизнес задача намного сложнее. Но не в этом дело. Мы с одной стороны понимаем что нам в любом случае нужна сериализация работы с календарем что бы не было конфликтов и невалидных данный в базе. С другой стороны, нам важно обеспечить высокий конкаренси на разных не конфликтующих датах.
з.ы.
Сейчас у нас это имплементировано с транзакциями в монго (прости господи). Там столько всего я еще не раобрался полностью как оно живет. Худо бедно работает. Но данные херачатся переодически, и когда в рантайме мы на эти стейти налаживаем еще правила всякие, на выходе иногда получаются неправильные данные. Потому как на деле можнт быть 20 воркеров получивших задачу что-то сделать с одним и тем же айтемом. Ну и перформанс на рид райт не ахти. А некоторые требование по запросам мы вообще выполнить не можем. Ну не подходит схема.
Вот пытаемся на sqrc + возможно event sourcing + materialized view и все это в рамках DDD запилить. Что бы и история была, вьюшки под разные запросы разные создавались, и что бы избавиться от проблем невалидных данных в базе. Только вот положить этот стейт на агрегат не можем. Грузить например 2 года календаря в память что бы изменить пару дней как-то некошерно. Можно поиграться и загрузить только релевантные данные в память если получиться (например стейты ближних дат для проверки
конфликтов и другие валидации) + по itemId, и после мутации сохранить опять в базу. Но опять же, мутаций много. Некоторе из них нужно выполнить очень быстро (может приоритет запросов на мутацию тут поможет).
Если еще добавить версианирование всего календаря, то юзер с дашборда вообще не сможет ничего сделать потому что версия документа будет часто меняться, хотя конфликтов по датам может и не быть.
Вобщем мозг взрывается =)) Может кто чего подскажет почитать, посмотреть.
З.Ы.
Может все таки у нас нет выбора кроме как грузить в память состояние календаря, но попытаться делать все так быстро что бы по максимому обеспечить throughput и компенсировать недостаточную конкурентность/параллельную обработку?
1. Первый закрылся через ~3 года, из которых я отработал полтора где-то. Зашел аккурат перед выходом в продакшен. Кто этого никогда не делал, вряд ли поймет что это. Скажем так, когда инвестору обещали выйти в мир через неделю, после почти года интенсивной разработки, а по итогу за 4 дня до релиза ты понимаешь что даже логин не работает потому что люди писавшие все это чудо на JS не понимали что такое асинхронность. Пришлось знатно попотеть.
2. Со второго уволили после 9-ти месяцев (стартап был очень маленький, решил расти, и директор думал что взять чувака и посадить за стол, без управления ни проектом, ни компанией со стороны менеджмента (его не было) будет работать так же хорошо как и когда в стартапе было 5 челоек. В итога год промучался я с каким то проектом который лежал в ящике как минимум год, и директор думал что я его закончу за пол года без намека не техзадание и минимального списка requirements). Директор просто хотел «что бы работало». В итоге разочаровался что я не закончил его проект, и мы расстались.
3. Уже четвертый год в 3ем стартапе. Процессы поставлены. Есть начальнки, есть менеджеры. есть техзадание и т.д.
Работы завал. Проблем завал. Легаси завал. Новых фичеров завал. Поддержка юзеров и багов, тоже завал. При этом, проблемы нетривиальные и интересные. Местами highload, event driven и т.д. Так же проблемы перформанса, легаси, тестов и т.д. Скажем так, распиливаем монолит который писался 5 лет все кому не лень. Можете представить себе объем работы. Да, приходится много блокеров чинить, и 2 ночи и в 7 вечера. Не для каждого. Но, вайб хороший, не скучно, и можно реально расти.
Не знаю как в других странах, но в Израиле, если ты не дурак, то за год в стартапе ты узнаешь и учишься тому что в большой компании возьмет года 3. Есть компании старые и большие, где люди по 9 лет работают, и все что они делают это запуск бэкапа скриптом. Остальное время поддерживают легаси… (я не говорю про гугл фейсбук и эппл… там немного подругому, но и в них ты маленький винтик).
Да, возможно в стартапе решения не всегда правильные (как думает разработчик). Где то решение хорошее, где-то заплатка, где-то POC, где-то решение нужно еще вчера. Но, тебе приходится самому учиться и трогать вещи начиная от настройки DNS и заканчивая оптимизацией базы данных. Ты сам делаешь исследования по выбору инструментов, и учишься на своих и на чужих ошибках. Ты растешь очень быстро.
Я после работы в стартапах ничего не боюсь в этой жизни =))
Но, если у тебя семья, то тут уже стартап не всем подойдет. Но, тоже зависит и от стартапа, и насколько плохой легаси оставили те кто давно уволился, да и сам бизнес.
Поправлю себя. Тут даже не бэкенд разработчики, а WPF. То есть возможно они всю жизнь пилили стэнд элон приложения с коннектом к базе, и тут им — держите реакт, походу разберетесь. Это риски которые менеджмент должен был учесть и оценить.
И тут я осознал, что React не дружественен ни к Java, ни к .NET разработчикам. Angular в этом случае был бы лучшим выбором из-за схожих шаблонов проектирования.
Это как? Депенденси инжекшен он и в африке… И если они бэкендистов заставили писать фронт, а не фуллстек/фронтенд разработчиков, то ожидаемо что они будут писать говнокод без энтузиазма. Хоть на ангуляре хоть на реакте.
И зря тут недооценивают разработчиков нет и жава. Сколько проектов видел написанных всякими жаваскрипт адептами которые раньше джеквери херачили. Зачем паттерны… это все овер, давайте без них. И быстро и кода меньше. А потом ни тестировать без магии жеста (Jest) ни поддерживать это гомно нельзя. Поэтому паттерны тут испортить ничего не могли, если естественно их применяли когда надо, а не паттерны ради паттернов.
Я никогда не видел двух проектов React с одинаковыми зависимостями, структурой проекта и руководящими принципами.
Ну если структуру делать feature based то она и на ангуляре разная будет.
А вообще такое чувство что просто недооценили сложность проекта учитывая что это новый стек для разработчиков, и думали щас как в ангуляре наклепаем формочек с двусторонним байндингом и крадом и в продакшен.
Вообще тут намешаны разные вещи не связанные с реактом от слова совсем. Билд берет время? Ну это проблема всей экосистемы ноды.
Могу согласиться только с тем что новые хуки и контекст добавляют магию и конвенции, и действительно не все их любят, включая меня. Ну и борьба с самим собой потому что на тебе лежит ответственность выбора библиотек, а не как в ангуляре — что дали тебе в фреймворке то и юзай. Хотя и там сторонних библиотек хватает. Redux это отдельная пестня…
Писать балансировку на клиенте не хочется, а ставить лоад балансер чтобы он держал конекшены и балансил все девопс пока не хочет…
Как я понимаю проблема эта может всплыть только когда нужны постоянные соединения. То есть, либо кип элайв, либо http/2 как у вас.
Resolving: total 3402
3402 пекеджей… Карл!!!
2.5G папочка node_modules… и это мы еще rush юзаем
Почему, достаточно понять по примеру вот этого пекеджа
github.com/i-voted-for-trump/is-even
Который стостоит, из…
Который состоит из
Который состоит из
Где-то мир свернул не туда…
Насчет безруких разработчиков. Тут проблема не в безруких. Проблема в разных. С разным бэкграундом, целями, возможностями, хотелками, опытом и т.д. И вот тут та свобода и «простота» которую дает JS выходит боком.
Но добавьте к этому еще то что весь хайп зарождался фронтендерами которые теперь могли писать бэкенд. Писали как умели. Добавьте к этом коллбэки и промисы и вообще асинхронную модель. Никаких тебе паттернов написания бэкенд сервисов. Синглтоны наше все. Тесты? О да. Давайте вначале нахреначим кода нетестируемого, а потом придумает JEST который магией поможет протестировать это все.
Если в в любом статическом языке вы 100 раз будете думать использовать ли рефлекшен, то услышать от JS разработчика «давай метапрограммирование здесь заюзеам, классная штука, я тут на конференции увидел» это нормально. Он даже не понимает какие последствия всего этого могут быть. Не хватает того что язык динамический и ты можешь себе выстрелить в голову через ногу, есть люди которые не боятся, как бы это сказать, возвести эту проблему в степень.
Да, согласен, поднять серверок за 2 минуты это круто. Запилить крад апи прямо в базу с монгуси, еще 5 минут. И если это изначально маленький проектик, то нет проблем. Но для больших проектов надо понимать, что за все придется платить.
И это я еще не говорю про то что многие не понимают разницу между CPU bound/IO bound. А если начинают понимать, начинают пизать решения типа форков, от которых меня тошнит.
Многие не доходили до проблема когда GC тупо съедает все CPU потому что такое количество инлайновых обьектов и стрингов создается что он не успевает очищать память…
Рефактор без компилятора, и даже с тестами — то еще удовольствие.
Мы вот нахавались, начали внедрять Type Script с надеждой что хоть часть проблем он уберет. С оставшимися научимся жить.
Проблема в том что многие пишут на JS скриптики или что-то простенькое, и не всегда доходят до проблем реальных приложений с нагрузкой и большой кодовой базой. Вот они будут хвалить JS.
Люди с опытом уже не так сильно будут радоваться тому что вебсервер поднять на експрессе с монго в 100 раз быстрее чем на жаве или дот нет, если знают что им нужно будет в будущем это поддерживать. Потому-что понимают во что это позже выльется. А если написать, и через 2-3 годика свалить, то норм. Уже не твои проблемы. Уже другому придется объяснять почему переименовать филд в проекте это месяц работы…
Но опять же, для POC или простых проектов, особенно IO Bound нода свою работу делает.
P.S.
А еще я всегда ржу что винда на пентиуме быстрее поднимается чем билд и приложение на ноде с +100500 зависимостями =)
Вы будете мечтать о компиляторе каждый раз когда будет прилетать эксепшен или блокер из-за самых тупых вещей. Когда весь проект написан на объектах, без нормальных моделей данных, вы будет открывать любую функцию, смотреть на параметры типа options, и гадать — а что там внутри?
Есть огромная разница между людьми которые пишут POC на JS и прыгают со стартапа в стартап и никогда не доходят до момента когда простенький POC вырос в гиганта и теперь кому-то с этим жить.
Когда проект, количество кода и разработчиков растет, с чистым JS работать невозможно. Но быстрый старт — это да… главное потом выжить.
А вы знаете что уже сегодня есть поколение разработчиков не видавших никогда колбэк хела уровней так на 10 со всякими вотерфолами? А потом еще обернутыми в промисы =))
Единственное что подкупает это то, что сериализация должна быть быстрей. Мы же любим все быстрое Ж) Но и тут я не уверен что это правило работает для всех платформ. (https://medium.com/@onufrienkos/benchmarking-performance-grpc-vs-rest-on-node-js-bf766127f170)
И что больше всего пугает это то, что старый ламповый RPC не очень то и популярен в связи с проблемами которые он приносит с собой. Почему же так хайпят на gRPC?
Хотелось бы видеть реальную пользу :/
даже если их будет 100, время потраченное на оптимизацию не окупится в ближайшие лет 10 =)
Поэтому можно неделю потратить на обсуждение формата ошибок с коллегами споря о кошерности того или иного решения.
Я обычно советую не изобретать велосипед, а посмотреть что делают гиганты и взять что то среднее.
Например фейсбук использует
Twitter
Ведь не от хорошей жизни они пришли к этому :)
Возможно мне нужно было уточнить что большинство мутаций у нас делается асинхронно.
Ну у нас такие доводы в пользу кафки (сейчас используем раббит и в основном без транзакций, потому что из еще не было в монге когда это разрабатывалось):
1. Пользователи насилуют систему как хотят и нам надоело иметь дело с параллельным процессингом или вообще обратным порядком команд. Например когда они делают Update -> Delete. На самом деле они могут делать много операций и нам это делает проблемы. С раббитом мы теряем order потому что скейлинг.
2. Кафка обеспечит нам partial order (партишенинг кафки по агрегату)
3. Опять же из-за партишенинга, у нас есть возможность использовать locality data patterns и работать с агрегатом при помощи load data -> mutate -> store, и не бояться что в соседнем воркере хэндлер тоже что-то сделал с этими данными.
4. Ну и в связке с DDD хотим топики и т.д. в любом случае.
5. В этом случае в принципе транзакции нам нужны только для «все или ничего с ролбэками». Боюсь что без этого транзакции убьют перформанс на нет когда все и вся будет ритраиться из-за конфликтов.
В принципе партишенинг можно и раббитом сделать, но там нет автоматического ребаланса консюмеров, а ручками мы это делать не хотим.
В реале речь идет о бронировании, не лотах. Так же бизнес b2b и каждая проблема с неправильными данными грозит потерей клиента. Например если вдруг 2 человека забронировали вещь, придется одному из них отказать, и возместить. Но с монги уйти не можем.
Не уверен что всех этих проблем можно избежать полагаясь только на транзакции. Тем более придется разбираться очень хорошо с изоляциями транзакций (например Serializable как я понимаю монго не поддерживает). Всякие фантомные ридс и т.д. Я то в конце разберусь, а вот остальные люди в компании — не уверен что все разберутся.
натягивать сову на глобуспопробовать имплементировать DDD для задач где есть работа с календарем?Например есть вещь и есть календарь у этой вещи. Любой человек может попросить попользоваться этой вещью на определенное время. Если запрос удовлетворен, то это вещь принадлежит определенному человеку на определенный период. Если нет, то в календаре состояние этой вещи на определенные даты отображается со статусом «pending» например. Статусы могут быть разными. Вещь можно передавать другому человеку, отменять и т.д. Может быт несколько запросов от разных человек на разные даты и они будут отображаться в календаре.
Можно смотреть на это вещи и из состояние. Допустим есть у нас:
Item {
id
title
…
}
state block {
id
startDate
endDate
itemId
status [available, pending, reserved, unavailable]
userId
}
У нас вот задача есть похожая но на порядок сложнее (для примера я ооочень сильно упростил), и мы вот думаем как впихнуть это в агрегат. И что-то сомневаемся…
1. Много конкурентных запросов и команд для определенной вещи от разных людей, апи и скедулеров которые в конце концов манипулируют стейтом. Создают, меняют даты, статус, овнеров и т.д.
2. Стейты могут накладывать друг на друга с разными датами, статусами и т.д по определенным правилам.
3. Нужно обеспечить целостность данных. Например 2 запроса одновременно могут увидеть что вещь свободна (!reserved, unavailable), и попытаяются зарезервировать его. В это время кто то может вручную заассайнить вещь на эти же даты на другого человека. И в это же время какой нибудь скедулер отменяет стейт в том же диапазоне дат потому что статус pending ничего не решает.
Вот что мы думаем.
1. Стейт блок как агрегат. Но, пользователи работают с датами календаря и вещами. Они не видят и не знают что это имплементировано в базе стейтами с айдишниками. Айдишники это скорее для девелоперов просто что бы оперировать данными в базе. Пользователи могут выбрать вещь и отменить пользование в определенных датах, а внутри уже наш код знает как обрезать стейты, делаить их или мержить. Их может быть несколько эти стейт блоков. Не вариант вобщем.
2. Item это агрегат рут. И вся работа со стейтами (календарем) будет идти через него. И так как он должен быть под транзакцией и никакого конкурентного доступа к нему не должно быть на запись по определению агрегата (если я не ошибаюсь), мы можем загрузить в память календарь этого агрегата по itemId, делать с ним что хотим, со всеми этими стейтами, пока остальные ждут, и потом сохранить. Чтобы не было конкурентного доступа на мутации будет кафка с партишенами по айтему ну и/или оптимистик лок и/или транзакции. НО — если человек хочет взять вещь на след неделе, на 4 дня, то его запрос будет ждать пока агрегат освободиться, потому что кто то зарезервировал пользование на сегодня и идет обработка. Ну то есть мы убиваем конкаренси тут конкретно, а нам она нужна.
На самом деле реальная бизнес задача намного сложнее. Но не в этом дело. Мы с одной стороны понимаем что нам в любом случае нужна сериализация работы с календарем что бы не было конфликтов и невалидных данный в базе. С другой стороны, нам важно обеспечить высокий конкаренси на разных не конфликтующих датах.
з.ы.
Сейчас у нас это имплементировано с транзакциями в монго (прости господи). Там столько всего я еще не раобрался полностью как оно живет. Худо бедно работает. Но данные херачатся переодически, и когда в рантайме мы на эти стейти налаживаем еще правила всякие, на выходе иногда получаются неправильные данные. Потому как на деле можнт быть 20 воркеров получивших задачу что-то сделать с одним и тем же айтемом. Ну и перформанс на рид райт не ахти. А некоторые требование по запросам мы вообще выполнить не можем. Ну не подходит схема.
Вот пытаемся на sqrc + возможно event sourcing + materialized view и все это в рамках DDD запилить. Что бы и история была, вьюшки под разные запросы разные создавались, и что бы избавиться от проблем невалидных данных в базе. Только вот положить этот стейт на агрегат не можем. Грузить например 2 года календаря в память что бы изменить пару дней как-то некошерно. Можно поиграться и загрузить только релевантные данные в память если получиться (например стейты ближних дат для проверки
конфликтов и другие валидации) + по itemId, и после мутации сохранить опять в базу. Но опять же, мутаций много. Некоторе из них нужно выполнить очень быстро (может приоритет запросов на мутацию тут поможет).
Если еще добавить версианирование всего календаря, то юзер с дашборда вообще не сможет ничего сделать потому что версия документа будет часто меняться, хотя конфликтов по датам может и не быть.
Вобщем мозг взрывается =)) Может кто чего подскажет почитать, посмотреть.
З.Ы.
Может все таки у нас нет выбора кроме как грузить в память состояние календаря, но попытаться делать все так быстро что бы по максимому обеспечить throughput и компенсировать недостаточную конкурентность/параллельную обработку?
1. Первый закрылся через ~3 года, из которых я отработал полтора где-то. Зашел аккурат перед выходом в продакшен. Кто этого никогда не делал, вряд ли поймет что это. Скажем так, когда инвестору обещали выйти в мир через неделю, после почти года интенсивной разработки, а по итогу за 4 дня до релиза ты понимаешь что даже логин не работает потому что люди писавшие все это чудо на JS не понимали что такое асинхронность. Пришлось знатно попотеть.
2. Со второго уволили после 9-ти месяцев (стартап был очень маленький, решил расти, и директор думал что взять чувака и посадить за стол, без управления ни проектом, ни компанией со стороны менеджмента (его не было) будет работать так же хорошо как и когда в стартапе было 5 челоек. В итога год промучался я с каким то проектом который лежал в ящике как минимум год, и директор думал что я его закончу за пол года без намека не техзадание и минимального списка requirements). Директор просто хотел «что бы работало». В итоге разочаровался что я не закончил его проект, и мы расстались.
3. Уже четвертый год в 3ем стартапе. Процессы поставлены. Есть начальнки, есть менеджеры. есть техзадание и т.д.
Работы завал. Проблем завал. Легаси завал. Новых фичеров завал. Поддержка юзеров и багов, тоже завал. При этом, проблемы нетривиальные и интересные. Местами highload, event driven и т.д. Так же проблемы перформанса, легаси, тестов и т.д. Скажем так, распиливаем монолит который писался 5 лет все кому не лень. Можете представить себе объем работы. Да, приходится много блокеров чинить, и 2 ночи и в 7 вечера. Не для каждого. Но, вайб хороший, не скучно, и можно реально расти.
Не знаю как в других странах, но в Израиле, если ты не дурак, то за год в стартапе ты узнаешь и учишься тому что в большой компании возьмет года 3. Есть компании старые и большие, где люди по 9 лет работают, и все что они делают это запуск бэкапа скриптом. Остальное время поддерживают легаси… (я не говорю про гугл фейсбук и эппл… там немного подругому, но и в них ты маленький винтик).
Да, возможно в стартапе решения не всегда правильные (как думает разработчик). Где то решение хорошее, где-то заплатка, где-то POC, где-то решение нужно еще вчера. Но, тебе приходится самому учиться и трогать вещи начиная от настройки DNS и заканчивая оптимизацией базы данных. Ты сам делаешь исследования по выбору инструментов, и учишься на своих и на чужих ошибках. Ты растешь очень быстро.
Я после работы в стартапах ничего не боюсь в этой жизни =))
Но, если у тебя семья, то тут уже стартап не всем подойдет. Но, тоже зависит и от стартапа, и насколько плохой легаси оставили те кто давно уволился, да и сам бизнес.
Это как? Депенденси инжекшен он и в африке… И если они бэкендистов заставили писать фронт, а не фуллстек/фронтенд разработчиков, то ожидаемо что они будут писать говнокод без энтузиазма. Хоть на ангуляре хоть на реакте.
И зря тут недооценивают разработчиков нет и жава. Сколько проектов видел написанных всякими жаваскрипт адептами которые раньше джеквери херачили. Зачем паттерны… это все овер, давайте без них. И быстро и кода меньше. А потом ни тестировать без магии жеста (Jest) ни поддерживать это гомно нельзя. Поэтому паттерны тут испортить ничего не могли, если естественно их применяли когда надо, а не паттерны ради паттернов.
Ну если структуру делать feature based то она и на ангуляре разная будет.
А вообще такое чувство что просто недооценили сложность проекта учитывая что это новый стек для разработчиков, и думали щас как в ангуляре наклепаем формочек с двусторонним байндингом и крадом и в продакшен.
Вообще тут намешаны разные вещи не связанные с реактом от слова совсем. Билд берет время? Ну это проблема всей экосистемы ноды.
Могу согласиться только с тем что новые хуки и контекст добавляют магию и конвенции, и действительно не все их любят, включая меня. Ну и борьба с самим собой потому что на тебе лежит ответственность выбора библиотек, а не как в ангуляре — что дали тебе в фреймворке то и юзай. Хотя и там сторонних библиотек хватает. Redux это отдельная пестня…