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
- объем данных до фильтрации.
- какие типичные объемы данных с фильтром, который пользователь вбивает в первую очередь? Какой разброс? Можно ли заставить сразу выбрать какую-то фильтрацию, или же нужно что-то показать сразу?
- какой характер данных, нужно ли будет пользователю реально листать страницы на практике?
- сколько параметров у фильтра (читай: "удастся ли эффективно реализовать все варианты фильтра")?
Как правило я принимаю одно из двух решений - или тупо 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