Entry tags:
Clojure, ленивость и отложенные отчеты
Очередной раз стукнулся об ленивость.
Делаю фоновый расчет отчетов - клиент просит у сервиса "посчитай мне отчет", тот ему возвращает идентификатор-ссылку на future со считалкой отчета и далее клиент опрашивает сервис на предмет "а не готов ли наш отчет" и тот ему отвечает либо "не готов" либо "готов, вот тебе данные".
Ну, склепал очередь отчетов - атом, в нем мап, в мапе идентификаторы запрошенных отчетов и future к ним. Запускаю - а оно мгновенно говорит, "да, вот отчет готов, забирай" и давай его считать и отдавать. В потоке запроса, не в рабочем потоке future.
Ленивость. Оно возвращает башку последовательности данных отчета сразу, "на тэбэ, дорогой, форси меня". И запрос готовых данных (в том числе, даже просто попытка в целях отладки посмотреть на мап с future) - вызывает форсинг последовательности.
PS: И еще обнаружил очередную фичу кложури - thread-local bindings протаскиваются во все вызовы, которые перекладывают работу в другие потоки. Т.е. конкретно тут - я в запросе часть общих параметров (типа имени пользователя) складываю в thread-local binding чтобы не протаскивать их руками через 100500 функций, думал, что при вычислении внутри future придется их доставать и перекладывать во второй поток - а оно уже сделано.
Авторы кложури не перестают удивлять своей крайней адекватностью и практичностью языка.
Делаю фоновый расчет отчетов - клиент просит у сервиса "посчитай мне отчет", тот ему возвращает идентификатор-ссылку на future со считалкой отчета и далее клиент опрашивает сервис на предмет "а не готов ли наш отчет" и тот ему отвечает либо "не готов" либо "готов, вот тебе данные".
Ну, склепал очередь отчетов - атом, в нем мап, в мапе идентификаторы запрошенных отчетов и future к ним. Запускаю - а оно мгновенно говорит, "да, вот отчет готов, забирай" и давай его считать и отдавать. В потоке запроса, не в рабочем потоке future.
Ленивость. Оно возвращает башку последовательности данных отчета сразу, "на тэбэ, дорогой, форси меня". И запрос готовых данных (в том числе, даже просто попытка в целях отладки посмотреть на мап с future) - вызывает форсинг последовательности.
PS: И еще обнаружил очередную фичу кложури - thread-local bindings протаскиваются во все вызовы, которые перекладывают работу в другие потоки. Т.е. конкретно тут - я в запросе часть общих параметров (типа имени пользователя) складываю в thread-local binding чтобы не протаскивать их руками через 100500 функций, думал, что при вычислении внутри future придется их доставать и перекладывать во второй поток - а оно уже сделано.
Авторы кложури не перестают удивлять своей крайней адекватностью и практичностью языка.
no subject
Ой, как разговор повернулся.
Я собаку съел на этом пейджинге. Я делал хитрожопые пейджинги с сортировками с фильтрациями в долбаном T-SQL на двадцать страниц кода. Я писал грид, который работает с кучей разных датасорсов - от тех что все свои 20 строк возвращают молча, до тех что шлют нахер и вообще не говорят сколько у них данных есть по твоему запросу. И правильно делают.
У тебя есть 100500 строк в базе по фильтру "А". Чтобы тебе хотя бы понять сколько там данных проходит по этому фильтру - тебе нужно сделать скан по всей гигабайтной базе, понимаешь? Речь даже не про то, что ID-шники твои метры весить будут. Речь о том, что даже count() сделать, чтобы показать сколько там вообще страниц - это уже жесть. Ты не видел таблицы со 100500 строк, нет?
Так понятнее? Умельцы вроде меня, блин.
no subject
Я нисколько не сомневаюсь в способностях сделать сложно. Под "умельцы" я подразумеваю умельцев которые говорят что консистентный пейджинг не нужен, потому что он сложен. А он банален если подумать.
no subject
А метод с ID-шниками - полумера, которая с большими данными не сработает, а с маленькими - только гемора принесет.
no subject
Чем сложнее фильтры, тем "оправданнее" мой подход. Про количество ты решись или "нужна только первая страница" или неразумное количество. Пока я нащупал границу 10 тысяч записей, больше никто не требует. Но начинаю с тысячи обычно. Если больше я выкидываю информацию "плиз заузить критерии" и все признают это обоснованным.
" В этом случае просто вытаскиваешь вообще все на клиента и пихаешь в грид. И сортировка у тебя сразу получается без доп. запросов, и дополнительная фильтрация - тоже мгновенная."
Чо серьёзно? Я вытаскиваю 1000 айдишников, которые все вместе занимают 10 килобайт и подтягиваю а ты предлагаешь тянуть 1000 записей, в которых каждая легко на старте килобайт, а в реальной жизни все 10. А таких гридов у меня три штуки на форму. Нуну. Успехов.
no subject
no subject
no subject
no subject
no subject
no subject
Проблема-то простая: структуры данных, по которой можно фильтровать и сортировать по любому полю в любых сочетаниях - не придумали еще. А на UI именно этого и хотят. Если данных мало - ок, будет у нас O(N). Если данных много - надо так или иначе ограничивать размер входных и выходных данных алгоритма.
Ну и речь вообще о том, что проблема высосана из пальца - дальше второй страницы мало кто ходит. Вот ты, когда гуглишь, как часто смотришь на вторую страницу выдачи?
no subject
no subject
no subject
no subject
Давайте не будем ругаться. Рассмотрим ситуацию сначала. ЕСТЬ требование сделать пажинейшн. Каково ваше решение не требующее гениального программиста (я ни капли не сомневаюсь в ваших способностях) для каждого грида?
no subject
- объем данных до фильтрации.
- какие типичные объемы данных с фильтром, который пользователь вбивает в первую очередь? Какой разброс? Можно ли заставить сразу выбрать какую-то фильтрацию, или же нужно что-то показать сразу?
- какой характер данных, нужно ли будет пользователю реально листать страницы на практике?
- сколько параметров у фильтра (читай: "удастся ли эффективно реализовать все варианты фильтра")?
Как правило я принимаю одно из двух решений - или тупо TOP и полностью все на сервере, или тупо выгрузить сразу всё. Вариант "выгрузить все" довольно просто можно урезать до "выгрузить все что нужно для сортировки и фильтрации", а все остальное - догружать при необходимости.
Как частный случай последнего способа, можно выгружать только ID, да. Но это фиговое решение - и интерактивности не получишь, и сэкономишь только в случае если юзер тыкает пейджер (редко), а не в сортировку/фильтр (чаще). Причем на сортировке и фильтрации ты еще и потреяешь, т.к. базе надо сканить больше данных. Универсальность такого решения тоже под вопросом: у него все равно есть предел по количеству входных данных, пусть и в несколько раз побольше.
Я делал универсальное решение - переключать режимы грида на лету. Источник возвращает столько данных, сколько считает разумным. Также опционально считает count. А если хочет - возвращает все. Если вернули все - переключаемся в клиентский режим, где можем сортировать и дофильтровывать (т.е. сужать фильтр) без участия сервера. Типа набрали "сер" - сходили на сервер, он отдал все подходящие 60 строк, скинули на клиент, и дальше можем дофильровать до "сервера" или "сервисы" автономно.
Если вернули больше страницы - можем листать страницы на клиенте в этих рамках. Сортировать не можем. Дофильтровывать можем если получается больше страницы данных.
Также, если нам не вернули count, то мы заменяем пейджер с 1,2,3..6,7 на 1,2,3..6,show more. Ну и еще куча всяких тонкостей.
Так все вообще прикольно пашет, но я не видел таких готовых решений.
no subject
- универсально, даже если есть ситуации где неоптимально (клиент наврал что пейджинг реально нужен и юзера не пейджат)
- сделать может любой индус, кто-то соображающий делает оптимальную вьюшку, индус получает набор всех айдишек в первом проходе и нужные айдишки во всех остальных
- элементарно реализовывается подкачивание только пары строк, если захочется сделать без страниц - скролл вниз с дозагрузкой
Резюмируя. Если бы нужно было написать один грид с пажинейшеном, и я бы видел что адекватный программер (вы например) за это берётся, я бы только сказал бы "делай". Но если надо сделать решение, которое универсально и любой условный "индус" (даром что не из Индии) может повторить/использовать. То я остаюсь при своём. В системах, с которыми я работаю - сотни гридов. И к сожалению нет во фреймворке готового решения для пажинейшна, вся эта дискуссия не праздна, меня задолбал зоопарк, который творят на каждой форме. В одном внедрении насчитал 5! разных форм работы с гридами (по количеству команд скорее всего). Я хочу сделать скроллинуемый "до бесконечности" (до тысячи но настраиваемо :) ) грид частью "общего" фреймворка.
no subject
no subject
no subject