metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2013-03-26 09:25 pm
Entry tags:

Clojure, ленивость и отложенные отчеты

Очередной раз стукнулся об ленивость.

Делаю фоновый расчет отчетов - клиент просит у сервиса "посчитай мне отчет", тот ему возвращает идентификатор-ссылку на future со считалкой отчета и далее клиент опрашивает сервис на предмет "а не готов ли наш отчет" и тот ему отвечает либо "не готов" либо "готов, вот тебе данные".
Ну, склепал очередь отчетов - атом, в нем мап, в мапе идентификаторы запрошенных отчетов и future к ним. Запускаю - а оно мгновенно говорит, "да, вот отчет готов, забирай" и давай его считать и отдавать. В потоке запроса, не в рабочем потоке future.
Ленивость. Оно возвращает башку последовательности данных отчета сразу, "на тэбэ, дорогой, форси меня". И запрос готовых данных (в том числе, даже просто попытка в целях отладки посмотреть на мап с future) - вызывает форсинг последовательности.

PS: И еще обнаружил очередную фичу кложури - thread-local bindings протаскиваются во все вызовы, которые перекладывают работу в другие потоки. Т.е. конкретно тут - я в запросе часть общих параметров (типа имени пользователя) складываю в thread-local binding чтобы не протаскивать их руками через 100500 функций, думал, что при вычислении внутри future придется их доставать и перекладывать во второй поток - а оно уже сделано.
Авторы кложури не перестают удивлять своей крайней адекватностью и практичностью языка.

[identity profile] berezovsky.livejournal.com 2013-03-26 07:38 pm (UTC)(link)
Кстати да. Как нормальный пейджинг делают?
Два селект топа каждый раз, или тянут всё на клиент и перекладывают на грид, или что-то промежуточное, вроде "посчитали конечную табличку, оставили на сервере, по мере листания на клиенте получаем из неё куски"?

[identity profile] metaclass.livejournal.com 2013-03-26 07:41 pm (UTC)(link)
Не знаю. Наверно выполняют запрос с select first/top/limit
Меня огорчает мысль о том, что этот запрос выполняется повторно на каждую страницу, поэтому теоретически, надо бы выполнить его один раз и закэшировать.

[identity profile] swizard.livejournal.com 2013-03-26 10:15 pm (UTC)(link)
> Меня огорчает мысль о том, что этот запрос выполняется повторно на каждую страницу, поэтому теоретически, надо бы выполнить его один раз и закэшировать.

Кстати, интернет-поисковики как раз перевыполняют запросы каждый раз при листании серпа, кэшировать им получается сложнее. При этом, что интересно, чем дальше листать, тем им технически печальней -- яндекс, например, принципиально дальше сотой страницы не пускает, даже если десять миллионов результатов найдено.

[identity profile] jakobz.livejournal.com 2013-03-26 09:17 pm (UTC)(link)
Делают select top каждый раз. Прикол в том, что никто списки дальше чем страницы на 3 не листает. Т.е. пейджинг - он только в теории нужен, а на практике надо нормальный UI со списками заголовков, фильтрацией, и т.п.

[identity profile] swizard.livejournal.com 2013-03-26 10:24 pm (UTC)(link)
Вот, кстати, совершенно согласен про ненужность пейджинга. Имхо он реально необходим только для двух вещей:
  • Чисто психологически, чтобы у пользователя не терялось ощущение, что вот они все данные, перед моими глазами, ничего никуда не пропало.
  • Когда надо найти "то, не знаю что" / "увижу глазами -- узнаю". Например, у меня так бывает изредка с платежами в истории инет-банка, когда не помнишь ни даты, ни одного из реквизитов.

[identity profile] sergiej.livejournal.com 2013-03-27 08:58 am (UTC)(link)
Если делать каждый раз топ на динамичных данных с критериями поиска то получается бред - можно на следующих "страницах" получать то что уже видел и "терять" на прошлых то чего не видел вообще.

[identity profile] metaclass.livejournal.com 2013-03-27 09:00 am (UTC)(link)
У меня обычно отчеты по неизменяемым данным, там проще.
А для динамических нужны какие-то более другие методы работы, в т.ч. и кэширование результата запроса.

[identity profile] sergiej.livejournal.com 2013-03-27 09:04 am (UTC)(link)
Не надо кешировать. Первым запросом берутся только айдишки да побольше, скажем страниц на 10, если больше говорим "заузь критерии, всё не влазит". Потом очередной набор айдишек кверится для каждой страницы с деталями, вот и всё. Обеспечено что пациент пролистав увидит все записи. Можно не листать а дописывать внизу вновь прочитанные - так намного удобнее, но не во всех гридах это возможно без извращений.
Пейджинг собственно только для того и нужен, чтобы особо недоверчивые были уверены что они "проверили всё глазками".

[identity profile] metaclass.livejournal.com 2013-03-27 09:10 am (UTC)(link)
Мы ID храним на клиенте, получается?

[identity profile] sergiej.livejournal.com 2013-03-27 09:13 am (UTC)(link)
Ну можно на миддлвере если трёхзвёнка. Хранить пару сотен айдишек это мелочь по сравнению со сложностью обеспечения правильного педжинга делая каждый раз запрос рейнджа. Да и для базы в итоге такое легче. Только один раз идёт запрос по сложным критериям, потом всегда "ин" по конкретным индексированым айдишкам.

[identity profile] metaclass.livejournal.com 2013-03-27 09:20 am (UTC)(link)
Заебись идея, в целом. Хранить IDшники гораздо легче, чем целиком результат.

[identity profile] sergiej.livejournal.com 2013-03-27 09:29 am (UTC)(link)
Может есть что-то более правильное, но это из опыта просто и быстро сделать.
Проблема только с хипстерскими базами, где нет айдишек, но там пейджинг это вообще секс в гамаке стоя :)

[identity profile] jakobz.livejournal.com 2013-03-27 09:03 am (UTC)(link)
Вот на это кладут вообще всегда и все.

[identity profile] sergiej.livejournal.com 2013-03-27 09:11 am (UTC)(link)
Клиент говорит оператору "у меня одна из фготеней была какая-то странная", посмотрите пожалуста. И оператору нужно найти нужную "фиготень" тупо пролистав все. Это очень частый случай если работать с корпоративом. Или клиент ищет товар в магазине, который помнит чисто визуально, а ты ему "прыгаешь" он это замечает, плюёт и уходит.
"Плевать всегда и всем" это чисто красноглазый подход. Поэтому вас к клиенту допускать нельзя на пушечный выстрел, приходят такие, и клиенту заявляют: "вы дураки, вам (никому) не нужно".

[identity profile] jakobz.livejournal.com 2013-03-27 09:24 am (UTC)(link)
Неа, париться за консистентность данных - это как раз красноглазый подход.

Ты пойди спроси у бизнеса что-нибудь типа такого: вот в этом списке, который секретарша твоя тыкает, может СЛУЧИТЬСЯ НЕКОНСИСТЕНТНОСТЬ!

Он такой: "чо?"

Ну ты такой объясняешь попроще. Типа листаем список на страницу 2, а на странице 1 уже новые данные появились. Что делать? Варианты такие:
- данные на момент открытия показывать ($199 чтобы добавить кнопку рефреш и $1000 на обучение персонала тыкать ее периодически, и покрытие косяков и нервных срывов у тех, кто тыкнуть забыл)
- делать рилтайм-добавление айтемов с клевой анимацией (всего $1599).
- забить болт ($0, ненулевая вероятность что какая-нибудь секретарша раз в год что-то там не найдет)

Как ты думаешь, что выберет бизнес?

Я думаю что только какие-нибудь фейсбуки, на каких-нибудь мега-важных ключевых главных страницах, решают подобные проблемы. Остальные прагматично кладут болт. А те, у кого по этому поводу свербит душа - как раз красноглазые и есть.

[identity profile] sergiej.livejournal.com 2013-03-27 09:32 am (UTC)(link)
может секретаршам и пофиг, в бизнес критических корпоративных системах - не пофиг.
Я годы жизни провёл на встречах, пытаясь клиента уговорить на изменения таких типа мелочей, но не сказав прямо что клиент идиот. Так вот такого типа требования "обеспечить показ всех затребованных данных"
это и есть консистентность, если потом запись со страницы убежит - будет открыт дефект и делать нормально всё равно прийдётся.
Тем более что сделать нормально совсем легко.

[identity profile] jakobz.livejournal.com 2013-03-27 09:43 am (UTC)(link)
Сделать нормально - сложно. Ок, взяли мы много ID-шников сразу для нескольких страниц.
Вопросы:
- сколько ID-шников взяли? Фильтрация, как правило делает скан по базе, элементов может быть много, запрос может быть сложный. Чем больше достаем - тем все сильнее начинает тормозить. TOP ограничивает скан, и мы как минимум первую страницу достаем быстро, а дальше люди ходят редко, сильно реже чем на первую.
- когда сбрасывать этот кэш? Что должно произойти, если мы на 2-й странице нажали F5? Что должно произойти если F5 нажали на первой странице?
- где хранить этот стейт? Сессия - таки не резиновая.
- все хорошо если у нас простая база. Что если у нас, как в этом самом ЖЖ, все кэшами в три слоя покрыто? Ну возьмем мы из второго кеша в третий - актуальности данным это не добавит. Надо делать push-обновления.

Пейджинг и рил-тайм вообще не очень дружат. Посмотри как сделано в том же самом жеже - он вполне может показать запись с предыдущей страницы, если в ленту запись добавилась. Никого это не парит вообще, это понятное поведение. Более того - я лично по этому делу понимаю что на первой странице появилось что почитать.

Вконтактик добавляет записи налету, и у него пейджинга нету. Может быть такой подход и лучше, но это уже неиллюзорно дороже в разработке.

[identity profile] sergiej.livejournal.com 2013-03-27 09:51 am (UTC)(link)
"- сколько ID-шников взяли? Фильтрация, как правило делает скан по базе, элементов может быть много, запрос может быть сложный. Чем больше достаем - тем все сильнее начинает тормозить. TOP ограничивает скан, и мы как минимум первую страницу достаем быстро, а дальше люди ходят редко, сильно реже чем на первую."
Вот именно, запрос мы делаем в моём решении только один раз. Вытащить в сложном запросе 20 или 200 айдишек это практически пофиг, а сделать 10 запросов по 20 это тяжелее намного

"- когда сбрасывать этот кэш? Что должно произойти, если мы на 2-й странице нажали F5? Что должно произойти если F5 нажали на первой странице?"
Когда поменял критерии поиска и(или) нажал "искать". Естественно он так на первый лист грида попадает.

"- где хранить этот стейт? Сессия - таки не резиновая."
зависит от языка, архитекруты итп. От курсора до JSON в браузере.

"- все хорошо если у нас простая база. Что если у нас, как в этом самом ЖЖ, все кэшами в три слоя покрыто? Ну возьмем мы из второго кеша в третий - актуальности данным это не добавит. Надо делать push-обновления."
Если я в этой системе работаю, то я знаю кеши и весь ад вокруг, естественно выбираю решение подходящее для этого ада. Если я не знаю как в моей системе работают кеши и как в ней сделать чтобы работало корректно - я иду искать другую работу. Не надо мешать задачи.

[identity profile] jakobz.livejournal.com 2013-03-27 09:57 am (UTC)(link)
>Вот именно, запрос мы делаем в моём решении только один раз. Вытащить в сложном запросе 20 или 200 айдишек это практически пофиг, а сделать 10 запросов по 20 это тяжелее намного

Вот именно в этом отличие теории и практики. Да, если тащить топом - надо будет сканить повторно. Но если посмотреть сколько раз юзеры открывают первую страницы, сколько раз - вторую, сколько раз - третью, то становится ясно что надо оптимизировать только первую.

>Когда поменял критерии поиска и(или) нажал "искать". Естественно он так на первый лист грида попадает.
А если юзер знает что у него айтем появился (новый пост в жж, соседняя секретарша вбила)? Как дать ему понять что вот этим действием он лазит по кешу, а другим - тащит свежие данные?

[identity profile] sergiej.livejournal.com 2013-03-27 10:03 am (UTC)(link)
Повторяю ЗАДАЧА ПЕЙДЖИНГА ЕСТЬ
ты предлагаешь её "не решать", предложение крутое, но как-то не удовлетворяет клиента. Про выдачу бреда на очередных страницах я уже всё написал.

Пациент понимает что он лазит по "кешу" если он хочет получить обновление - нажимает поиск. Не встречал ни одного юзера, который не понимает что перелистывание на другую страницу не значит перепечатывания книжки наново. Конечно умельцы типа тебя последнее время пытаются сломать мозг юзеру, ломая этот банальный принцип. Потом получается фейсбук, где вообще непонятно что где когда откуда и почему прыгает.

(no subject)

[identity profile] jakobz.livejournal.com - 2013-03-27 11:19 (UTC) - Expand

(no subject)

[identity profile] sergiej.livejournal.com - 2013-03-27 11:22 (UTC) - Expand

(no subject)

[identity profile] jakobz.livejournal.com - 2013-03-27 11:29 (UTC) - Expand

(no subject)

[identity profile] sergiej.livejournal.com - 2013-03-27 11:54 (UTC) - Expand

(no subject)

[identity profile] jakobz.livejournal.com - 2013-03-27 17:05 (UTC) - Expand

(no subject)

[identity profile] sergiej.livejournal.com - 2013-03-27 17:30 (UTC) - Expand

(no subject)

[identity profile] jakobz.livejournal.com - 2013-03-27 17:33 (UTC) - Expand

(no subject)

[identity profile] berezovsky.livejournal.com - 2013-03-27 17:35 (UTC) - Expand

(no subject)

[identity profile] metaclass.livejournal.com - 2013-03-27 17:45 (UTC) - Expand

(no subject)

[identity profile] jakobz.livejournal.com - 2013-03-27 17:50 (UTC) - Expand

(no subject)

[identity profile] berezovsky.livejournal.com - 2013-03-27 18:01 (UTC) - Expand

(no subject)

[identity profile] sergiej.livejournal.com - 2013-03-27 17:35 (UTC) - Expand

(no subject)

[identity profile] jakobz.livejournal.com - 2013-03-27 17:37 (UTC) - Expand

(no subject)

[identity profile] sergiej.livejournal.com - 2013-03-27 17:57 (UTC) - Expand

(no subject)

[identity profile] jakobz.livejournal.com - 2013-03-27 18:32 (UTC) - Expand

(no subject)

[identity profile] sergiej.livejournal.com - 2013-03-27 18:57 (UTC) - Expand

(no subject)

[identity profile] berezovsky.livejournal.com - 2013-03-27 19:33 (UTC) - Expand

(no subject)

[identity profile] metaclass.livejournal.com - 2013-03-27 19:40 (UTC) - Expand

(no subject)

[identity profile] sergiej.livejournal.com - 2013-03-27 19:59 (UTC) - Expand

[identity profile] jakobz.livejournal.com 2013-03-27 10:08 am (UTC)(link)
Вообще мой поинт не в том, как правильнее делать. Я оба варианта юзал. Я даже делал грид с гибридным вариантом, там вообще прикольно получилось. Типа датасорсу говорят "дай мне минимум 20 строк", а он может вернуть просто больше, а может вернуть все вообще и поставить про это галку. А UI потом от этого пляшет у себя - ходить ему на сервак за новыми порциями, или нет. Фильтрация, сортировка и пейджинг независимо переключались между клиентским и серверным режимом.

Мой поинт в том, что вместо того чтобы оба варианта с недостатками. А главное - что вместо того, чтобы за это все париться, гораздо полезнее за то же время допилить поиск и фильтрацию.

Потому что листать страницы - реально последняя мера для юзера, после того как не получилось отсечь все нужное поиском и вывести так, чтобы все было перед глазами на одном экране.

[identity profile] sergiej.livejournal.com 2013-03-27 10:24 am (UTC)(link)
"Потому что листать страницы - реально последняя мера для юзера, после того как не получилось отсечь все нужное поиском и вывести так, чтобы все было перед глазами на одном экране. "
да забудьте про ЖЖшки и вконтактики. В реальных бизнес задачах реального энтерпрайза якобы "реально последняя мера для юзера" это очень частая задача. Приведу пример ещё один, надо мне распечатать отчёт на 20 страниц. Но предварительно проверить не попал ли туда бред случайно. Если я посмотрю только на первую страницу это будет ок? Или мне все 20 страниц одним списком показывать и пусть скроллят?
Я даже хуже скажу, предвижу что с развитием "пальцевых" интерфейсов проблема консистентного пейджинга станет ещё более остро, тот бардак и индусятина которая позволяется сегодня не выдержит проверки временем. ТАкое моё ИМХО.
А сделать догрузку "новых" результатов в конце списка другим цветом (а в процессе перелистывания зажечь звёздочку что появились новые) это тоже легко и просто с моим механизмом.

[identity profile] volodymir-k.livejournal.com 2013-03-27 10:53 am (UTC)(link)
Если речь идёт о бухгалтерии/финотделе и прога например должна показывать, какие поступления на счёт пришли -- за предложение "показывать херню" могут указать на дверь. Особенно если бухгатлерша в день отвечает на 100 звонков вида "дошли ли мои тыщабаксов".

[identity profile] jakobz.livejournal.com 2013-03-27 11:33 am (UTC)(link)
Мне почему-то кажется, что речь идет о юзкейсе, когда в софтине нет какой-то нужной фичи, скажем "посчитать сумму того-то". И тогда бухгалтерша берет калькулятор и начинает считать, тыкая пейджинг.

Мне сложно представить ситуацию когда нельзя автоматизировать задачу "просмотреть портянку на 10 страниц, найти то-то и посчитать то-то". В крайнем случае, когда надо универсально и дешево - делается тупо выгрузка в Excel.

[identity profile] jakobz.livejournal.com 2013-03-27 11:37 am (UTC)(link)
На вопрос "дошли ли мои тыщабаксов" можно ответить отфильтровав по части названия клиента, и тыкнув сортировку по дате. Также можно ответить на кучу других подобных вопросов.