Fork me on GitHub
#clojure-russia
<
2017-06-13
>
razum2um04:06:08

кстати да, @misha есть ли история почему для map так вышло, была например memfn, депрекейтнули..

niquola05:06:23

Еще вариант - @parens-control

mike_ananev07:06:27

народ, а с каким storage driver'ом вы запускаете docker? devicemapper, что по умолчанию у докера для RHEL/CENTOS, не рекомендуется. Судя по описанию zfs самый рекомендуемый. А как его готовите вы?

misha09:06:07

@razum2um потому что map на скобках написан, а . и .. - на джаве. ну и джава методы не IFn вроде но это очень неполный ответ

misha09:06:46

чуваки пишут, что "как методы могут быть first class в кложе, если они не фёст класс даже в джаве?"

misha09:06:06

в memfn нельзя было тайпхинты просовывать, поэтому #() лучше в этом смысле

niquola10:06:41

Ребята давайте зафоловим и распространим наш новый групповой аккаунт - эту неделю его будет вести Миша!

misha11:06:56

(не я)

leov11:06:24

мип-мип. а на чём можно подключаться к постгресу, и как модно делать самые примитивные миграции? у меня тут новый пустой лайн-проект)

leov11:06:03

а пул соединений к постгресу и орм?

leov11:06:13

спасибо, кстати

niquola11:06:40

@leov - отсюда можешь повыдергивать - https://github.com/niquola/clj-pg

leov11:06:55

о, ништяк

leov11:06:22

маунт лайт ❤️

niquola11:06:59

скоро выпилим - ему там не место 😞

leov11:06:37

ну я не знаю, я просто никогда на кложе к скл не подключался. к редису только

leov11:06:40

ща вот буду пробовать

leov11:06:48

уже немного пугаюсь слов ждбц и прочего

leov11:06:53

например количества библиотек)

andfadeev12:06:45

тогда наверное стоит с базовых вещей начать, db-spec + jdbc и поделать запросы строками, потом навернуть уже каконить пул (hikaricp, c3po и т.д), а потом выбрать dsl для написания sql (honey, hug и т.д)

be913:06:37

посоветуйте за архитектурку. нужно реализовать семейство web-скрейперов. в ООП я бы реализовал это примерно так: https://gist.github.com/be9/afec3f30ac6496b4aa3a845116da7ceb а как это грамотно сделать в Clojure?

misha13:06:12

на протоколах можешь почти 1в1 так же написать

be913:06:14

т.е. скрейпер - это некий набор “методов“, каждый из которых выдирает из сайта свои данные. не все скрейперы поддерживают все методы. и есть состояние, т.е. куки должны обновляться по мере вызова

be913:06:12

а state как мейнтейнить? просто возвращать из методов?

artemyarulin13:06:23

я б завел один атом для всего, а все остальное сделал бы стейтлесс

be913:06:55

атом типа аргументом передавать?

artemyarulin13:06:26

и еще бы анально огородил весь IO и передавал httpFetcher бы тоже параметром (который бы в себе уже юзал куки/сессии), при таком подходе покрыть все тестами бы было вааще просто (а со скраперами охота чтоб тесты были, ломается ж от чиха всегда все).

be913:06:42

там логику HTTP запросов сложно вынести отдельно

artemyarulin13:06:07

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

artemyarulin13:06:41

Ну ага, это во мне хаскелист проснулся наверно 🙂

be913:06:26

дык сессия внутри транспорта

artemyarulin13:06:53

ну ага. На каждую итерацию берешь значение стейта из атома, создаешь транспорт с этим стейтом (cookieJar все дела) и передаешь скраперу

be913:06:48

а транспорт - это будет замыкание? ну типа

(defn make-transport [session]
  (fn [url params]
    ; что-то мутим с url, params и session
  ))

y.khmelevskii14:06:37

@leov я тоже использую joplin. Мне удобно, плюс он умеем миграцию в кучу разных баз делать

leov14:06:15

спс. я ща это всё буду честно копировать, из того репозитория выше, у @nicola .

artemyarulin14:06:04

@be9 дада, замыкание - poor man object 🙂

y.khmelevskii14:06:00

ну миграции в clj-pg я не нашел

artemyarulin14:06:06

т.е. по сути 2 стиля - ооп где у каждого скрапепа свой внутренний стейт (может неявный в виде мутирующего транспорта, куки опять же) либо один явный где-то повыше (манагер скраперов какой). Я бы выбрал второе ибо когда пойдут запросы один скрапер вернул что сайт упал, надо остановить все скраперы или логику что только 1 скрапер может дергать один ресурс одновременно и пр. то при втором подходе такое можно будет сделать легко

artemyarulin14:06:52

но я хз, если у тебя там лабораторная работа или в продакшене нужно быть уже вчера то нафег надо конечно 🙂

artemyarulin14:06:02

а, и обязательно скрапь все регэкспами - DOM/XPath/CSS selectors для хипстеров troll

be914:06:01

хехе, у меня не лаба. для скрапинга есть опыт с hickory, ничё так

artemyarulin14:06:39

А ну значит уже в курсе 🙂

be914:06:57

ещё вопросик: как подтащить в такой архитектуре connection-pool? его в манагере что ли создавать? https://github.com/dakrone/clj-http#persistent-connections

artemyarulin14:06:38

дак ага, как раз такое и делать там. А как бы это сделал в ОПП стиле?

artemyarulin14:06:54

у каждого скрапера свой бы пул был?

misha14:06:36

> там логику HTTP запросов сложно вынести отдельно например какую?

artemyarulin14:06:24

ну даже теже сессионные куки. Проще по дефолту отдать это трансапорту чтоб он сам внутри все мутировал и дергал. А руками уже доп работа

misha14:06:07

ну это ж контекст, который нужно проталкивать с каждым последующим запросом той же цепочки

misha14:06:23

тут, наверное, подходы идентичные подходам написания компонентов для юая: "локальный стейт компонента хранить в компоненте, в родительском компоненте или в глобальном атоме?"

misha14:06:29

а нажатия на кнопочки, меняющие стейт компонента - это аналог запроса, который потом стейт куки мутирует

artemyarulin14:06:49

ну дада, явный контекст пизже конечно 🙂

misha14:06:02

все плюсы и минусы тупо те же: "шумный функциональный код" против "лаконичного хер отдебажишь кода"

misha14:06:48

инструменты, вроде бы, тоже те же: колбеки, кор-асинк, стейт-машины

misha14:06:37

только переход между состояниями - респонс вместо он-клика

artemyarulin14:06:16

еще конечно тестирование первого просто сказка. У меня счас проект хоть и на TS но IO везде транспортом\параметром передается, test coverage под 100% и всякие сложный кейсы покрываются на ура. Не говоря уж про отсетсвие багов связанных с этим

be914:06:23

> у каждого скрапера свой бы пул был? ну да, они независимы друг от друга

artemyarulin14:06:57

странно, я б один общий делал

be914:06:31

в данном случае это некритично

be914:06:32

> только переход между состояниями - респонс вместо он-клика скрейперы можно писать синхронным образом

be914:06:54

@artemyarulin а как бы ты делал?

artemyarulin14:06:09

ну ессно асинхронно все

artemyarulin14:06:26

один сайт отвечает 10 сек, чо теперь ждать чтоль

be914:06:04

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

be914:06:32

на вложенных коллбеках а ля node.js?

artemyarulin14:06:36

аа, ты про это ок

artemyarulin14:06:51

я думал прям тред блокируем, ждем все дела)

be914:06:35

да я бы и блокировал по простоте душевной 🙂

be914:06:33

clj-http.client предлагает коллбэки https://github.com/dakrone/clj-http#async-http-request

be914:06:22

5 вложенных коллбеков, по-моему, чуть более плохо, чем полностью

misha14:06:59

так корасинк, чтобы оно плоским стало

artemyarulin15:06:45

вообще я б очередь тасок замутил, а может и не одну

misha15:06:11

да, сетуют, что корасинк дебажить тяжело.

be915:06:53

> очередь тасок замутил, а может и не одну очередь тасок там будет сверху

misha15:06:58

а если превратить скрейпинг в чистый код, с единственным ио - запросом - можно тупо в очередь в атоме писать

be915:06:39

> а если превратить скрейпинг в чистый код, не очень понимаю, как это сделать. методы устроены примерно так: 1. запросить страницу A 2. выдрать данные и запросить страницу B 3. и т.д. каждый следующий шаг зависит от предыдущего

be915:06:41

всякие http://asp.net и джавовские бекенды сайтов, которые мне нужно скрейпить, любят сабмитить кучу форм, всякие редиректы там, псевдо-редиректы (где страница состоит из одной формы, которая тут же постится в window.onload)

be915:06:45

т.е. несчастный логин на сайт может включать в себя 5 последовательных запросов

be915:06:40

такое очень просто написать синхронно, и не очень понятно, как сделать это асинхронно

misha15:06:38

ну как ты будешь с этим справляться по-умолчанию?

misha15:06:46

всякие фоллоу-редиректс обрабатываются самим clj-http? или ты руками будешь вот это вот всё?

be915:06:01

руками

misha15:06:07

если за тебя это делается, то у тебя остаются 2 типа функций: - из страницы выпарсить инфу в базу и форму для сабмита - по форме для сабмита получить следующую страницу

misha15:06:07

если руками, то, впринципе то же самое, только вместо 1 реквеста шага - 5, что бы все редиректы обойти

misha15:06:41

типа в очередь кладешь таск {:url ... :cookies {...} :formdata {...}}, воркер берет таск из очереди, получает страницу, на основе которой кладет в очередь еще N подобных тасков

misha15:06:34

(а во вторую очередь, например, чо там выпарсил со страницы чтоб в базу положить)

misha15:06:45

суешь очередь в канал, на него трансдюсер, который запросы отправляет, и на конж выступать с докладом едешь

misha15:06:32

еще слышал, как чуваки пьедестал исключительно для пайплайнов на интерсепторах использовали: http://pedestal.io/reference/interceptors

misha15:06:06

в принципе - то же самое +-

be915:06:12

вместо одной синхронной функции в 50-70 строк получается черт знает что

be915:06:23

какие-то воркеры, таски итп

be915:06:38

микрокусочки кода в разных местах

misha15:06:22

у тебя строк 50 займет только по редиректам всем пройтись наверное.

misha15:06:39

без монады не разобраться troll

be915:06:06

у меня просто уже есть реализация простецкая. я зашёл сюда узнать, как можно сделать лучше. и понеслась..

misha15:06:31

ну всё же зависит от определения "лучше"

misha15:06:22

если 100 строк лапши делают всё, что тебе надо, то и нечего улучшать-то

be915:06:53

У меня сейчас синхронная лапша, интересно как сделать асинхронно без регистрации и СМС :)

be915:06:50

Ну а если все сложно, буду гонять синхронщину в отдельных тредах, да и всё

misha15:06:24

всё как раз simple ::kappa: очереди - отдельно, воркеры - отдельно

akond15:06:44

если я пишу под ноду, то есть ли способ не городить колбеков вокруг, например, fs.readFile(...)?

akond15:06:01

а выпрямить этот дело как-нибудь по типу ->

misha15:06:00

корасинк opieop

be916:06:16

В ноде есть fs.readFileSync

be916:06:09

А ещё с недавних времен там есть await, который все промисы выпрямляет

be916:06:25

Одна беда: жабоскрипт остаётся сам собой и аромат жженого синтаксического сахара никуда не девается..

artemyarulin16:06:23

согласен с @misha - если задача на раз/два то пофег. А если Ынтырпрайз то retry logic, редикерты, очереди, ошибки, логи и прочая. Воркеры и очереди просто проще будет изменять и реализовывать все эти фичи

artemyarulin16:06:49

я уж не говорю про блокировку тредов - с ними у тебя реквестов 5 в секунду в среднем будет от силы

artemyarulin16:06:32

но ок не 5 конечно по “маловато будет“(с)

artemyarulin16:06:32

а если взять RabbitMQ или в каффку складывать например все, да все на амазоне поднять с автоскейлингом то уууу :))

be916:06:19

Всю эту хрень с очередями сложно отлаживать, а задачи захватить Землю нет.

be916:06:15

Интересует не пропускная способность, а простота и красота решения, вот

be916:06:39

Про протоколы я вкурил, спс

misha16:06:53

а простота - это симплота или изота в этом случае?

be916:06:10

Этим distinction не владею. Простота — это адекватность технических средств решаемой задаче. Тяжесть "лечения" не должна превышать тяжесть "заболевания".

misha17:06:46

господа, как такое кошернее (билдином каким-то, без рекура самописного) записать?

((fn [x f times]
  (loop [n times r x]
    (if (zero? n)
      r
      (recur (dec n) (f r)))))
 10 inc 5)
=> 15

Roman Liutikov21:06:13

@misha (reduce inc 10 (range 5))

misha22:06:55

Wrong number of args (2) passed to: core/inc

misha22:06:56

вообще, идея такое завернуть в функцию/макрос, принимающую x, f, и кол-во вызовов f

(-> x f f f f f)

misha22:06:35

есть repeatedly, но она для zero-args side-effect fns