C map/filter оно сильно просто получилось, т.к. функция по сути одна, которая балково получает список появившихся/изменившихся/удалённых записей которые нужно обработать и выдаёт что нужно добавить/удалить в целевой коллекции. А с map/reduce сложно, у меня тут пять функций:
◾️ map, почти тот же map/filter, превращающий список изменений в список ключей в целевой коллекции с какими-то данными относительно него
◾️ тривиальная функция создания первоначального аккумулятора, получающая ключ-значение из целевой коллекции и как там ей нужно инициализирующая вектор байт с данными аккумулятора
◾️ reduce, получающая аккумулятор и список данных из результата map, мутирующая аккумулятор
◾️ опциональная функция merge аккумуляторов (по сути reduce аккумуляторов). Если она есть, то это разрешает параллелить весь процесс, делая reduce'ы разных пачек данных, а затем объединяя аккумуляторы между собой, чтобы получить итоговый. Если её нет — то на весь процесс агрегации будет создан один уникальный аккумулятор и всё проредьюсится с ним
◾️ apply, которая берёт финальный аккумулятор и решает что записать в значение в целевой коллекции/удалить его
Решил, что лично я когда буду использовать эту штуку не буду гореть желанием описывать множество тестов, которые определяют полмира («есть вот такие-то изменения в изначальной коллекции», «есть такие-то записи в конечной», «вот такой должна стать конечная коллекция»), т.к. во-первых чтобы всякие кейсы разные потестить — это нужно будет много экранов копипасты делать, во-вторых обычно ошибки не в том как мы это всё объединили, а в самих шагах. Так что пока делаю возможность описывать тесты для каждой из этих функций в отдельности. Первую уже тестирую, вторую сегодня закончу. Дальше должно будет бодрее пойти, оно не сильно прям чтобы сложно было. Самое сложное — что нужно код сериализации/десериализации моих тестовых данных писать, а не тестировать 🙂
Как закончу, посмотрю, насколько сложно будет переиспользовать написанное, чтобы цепочку из этого добра составить, может и возможность определения интеграционного теста тоже добавлю. Будет полезно, ибо эти yaml-тесты из примеров выполняются как тесты проекта.
Я по приколу запустил измерение покрытия, кстати, удивился, там чуть больше 50% оказалось, если правильно смотрел. Но оно и не удивительно, этот звездолёт сильно сложно было бы просто на глаз делать и верить, что после каких-то доработок оно не выдаёт мусор и не удаляет все данные из базы :). А с TDD цикл между написанием кода и получением результатов его работы довольно неплох, удобнее чем какую-то программу целиком запускать и смотреть что она наделала.
После того как с тестами доразберусь, останется только в CLI добавить возможность запускать и этот вид трансформации, написать клея который будет получать команды от той логики агрегации, вызывать wasm-функции, возвращать результаты обратно и почти заживём, можно будет даже делать что-то.
Но чтобы оно действительно что-то делало, нужно будет ещё реализовать возможность из wasm-кода просить загрузить ключи вокруг определённых ключей, делать фантомные записи, чтобы иметь возможность реализовать подсчёт перцентилей имеющимися методами map/filter, map/reduce (
https://t.me/alexandersmind/482 ,
https://t.me/alexandersmind/483 ). А затем и нативно их поддержать, чтобы не приходилось этот бойлерплейт реализовывать в васме/шустрее работало. Надеюсь хоть к концу этого года допишу до результата который за два месяца на ноде накидал >_<
#diffbelt