
Igor
25.01.2018
15:17:15

Руслан
25.01.2018
15:20:33
ну да, давно названия не повторял)
interface EventHandler {
fun onEvent(event: Event) {
when (event) {
is AddEvent -> onEvent(event)
is RemoveEvent -> onEvent(event)
}
}
fun onEvent(event: AddEvent) = default(event)
fun onEvent(event: RemoveEvent) = default(event)
private fun default(event: Event) {
println(event)
}
}
конкретный сервис реализует интерфейс, имплеменит нужные onEvent'ы
получается простыня в EventHandler, но что поделать

Google

Dibro
25.01.2018
15:23:20
дак какая разница тогда?

Руслан
25.01.2018
15:23:54
Ну разница в том, что when только в одном месте?
Как было сказано - 100 ивентов всего, сервису интересны 10-20. В EventHandler простыня на 200 + C строк, в конкретном сервисе - просто вызовы методов/обработка
Если сервису нужно 10 ивентов - будет override 10 однострочников
раньше нужно было when распихать по всем сервисам

Ivan
25.01.2018
15:45:24
вообще меня изначально интересовало вообще это в байткоде можно сделать или нет

Руслан
25.01.2018
15:46:14
ну sealed класс будет умееть свитч по интам
так что будет быстро

Ivan
25.01.2018
15:46:54
хотел сначала написать что медленно, но вспомнил Ваш коммент про sealed классы и инты
в джавке свитч по классам можно сделать разве только через class.getName()
а это жара с хешкодами

Google

Igor
25.01.2018
15:59:03
А тут anko-sqlite никто не использует?
Не могу понять, оно experimental или уже нормальное и можно использовать?


Boris
25.01.2018
16:02:00
если кому-то интересно, чем кончилась моя котовасия к корутиноканалами, то вот: у меня был кейз (коммуникация с гитхабом), мне надо было сделать несколько поисковых запросов, резульаты склеить в один канал, отфильтровать, потом по каждому элементу из рузальтата сделать отдельный запрос (тут надо было распараллелить, чтобы значительно ускорить этот процесс) и чтобы на выходе получился канал в котором бы появлялись результаты по мере их получения. Я сделал для клиента корутиновый метод send, затем реализовал метод send, который возвращает канал в котором были значения по одному на каждую страницу резульатов, затем я добавил метд merge, который просто последовательно копировал в один канал элементы из всех суб-каналов, затем я добавил метод map идентичный натуральному, только с дополнительным парамером capacity который позволял расширить канал, потом внутри мапа я запускал запросы в потоки async, на выходе получился канал Deferred-ов, сделал метод который разворачивал дефереды селектом и складывал в канал дальше, на выходе я это всё фильтрую, дистиктю и отдаю из сервиса
https://gist.github.com/fogone/e940de35f755c13299a65733c4b3be59
Сори за говнокод
Но суть я думаю передает


Sergey
25.01.2018
16:40:54
ReceiveChannel<T>.map так есть же такое в самой либе?

Boris
25.01.2018
16:42:00
Я же в описании написал
Что он идентичный, только можно capacity передать

Sergey
25.01.2018
16:44:54
а распаралеливание не делал еще?

Stas
25.01.2018
16:47:05
На нной итерации получится rx

Boris
25.01.2018
16:50:10
Просто распараллеливаются не все шаги, а только один
Мне так и надо было
См. fetchFullPrInfo

Kirill
25.01.2018
16:53:16
Не бейте за флуд только :)

Sergey
25.01.2018
16:53:28
хм, спс, наверное как раз то что надо мне

Boris
25.01.2018
16:54:47
Да, всё так ?
Конечно хотелось бы, чтобы хорошо проработанные средства для распараллеливания были из коробки, думаю это вопрос времени

Igor
25.01.2018
17:09:51

Boris
25.01.2018
17:10:46

Google

Igor
25.01.2018
17:12:12

Boris
25.01.2018
17:12:14
Я бы эталонным этот код не назвал, но даже и не смотря на это написать попроще боюсь не выйдет
Чейн не самоцель, у него просто есть удобства, которые императивному походу не свойственны
Декларативность, хорошая модуляризация и гибкость в изменении отдельных шагов, краткость, хорошая расширяемость готовыми операциям
если и свои проблемы, конечно

Igor
25.01.2018
17:25:16
Имхо в RX единственное что важно тк его “поток событий”, который и отличает его от тех же промисов (те RX ~= Observable)
А когда мы начинаем накручивать “бизнес логику” на операторах рx (или юзать Maybe/Single/Completable) - значит что где то мы свернули не туда.

Boris
25.01.2018
17:26:04
а где тут бизнес-логика? получить данные-то это бизнес-логика?

Igor
25.01.2018
17:26:29
Мердж, фильтрации и всякие хитрые объединения и изменение порядка

Boris
25.01.2018
17:28:07
а тоже самое в sql-е тебя не смущает? часто бизнес-логику в sql-е пишешь?

Igor
25.01.2018
17:29:08
Смущает конечно, но это уже не касается котлина и вообще это имхо.

Boris
25.01.2018
17:29:46
а это вопрос не котлина, это вопрос изоляции
к тому же это всё равно придется сделать в этом сервисе, цепочкой или нет


Ivan
25.01.2018
18:01:51
если кому-то интересно, чем кончилась моя котовасия к корутиноканалами, то вот: у меня был кейз (коммуникация с гитхабом), мне надо было сделать несколько поисковых запросов, резульаты склеить в один канал, отфильтровать, потом по каждому элементу из рузальтата сделать отдельный запрос (тут надо было распараллелить, чтобы значительно ускорить этот процесс) и чтобы на выходе получился канал в котором бы появлялись результаты по мере их получения. Я сделал для клиента корутиновый метод send, затем реализовал метод send, который возвращает канал в котором были значения по одному на каждую страницу резульатов, затем я добавил метд merge, который просто последовательно копировал в один канал элементы из всех суб-каналов, затем я добавил метод map идентичный натуральному, только с дополнительным парамером capacity который позволял расширить канал, потом внутри мапа я запускал запросы в потоки async, на выходе получился канал Deferred-ов, сделал метод который разворачивал дефереды селектом и складывал в канал дальше, на выходе я это всё фильтрую, дистиктю и отдаю из сервиса
https://gist.github.com/fogone/e940de35f755c13299a65733c4b3be59
а как задача звучит совсем верхнеуровнево? Если без каналов и тому подобного?


Boris
25.01.2018
18:02:25

Ivan
25.01.2018
18:02:41
у проекта? или у ряда проектов?
а, проекты?
или пулл-реквесты?

Boris
25.01.2018
18:04:25
пул-реквесты
да это по сути не так и важно

Google

Boris
25.01.2018
18:04:52
просто там целый флоу их получения
не просто запрос послать
поиском сначала ищутся пр-ы, потом по ним получаются детали

Ivan
25.01.2018
18:06:25
ну на входе получается список? Просто, насколько, я понял корутины-way - это написать последовательный код и дальше добавить саспенд модификаторов и соответствующих корутин-билдеров

Boris
25.01.2018
18:08:48
ну вот если каналами драйвить, то друой вей
см. код
выше

Andrew
25.01.2018
18:14:01
Вопрос по коду выше. В чём суть select с единственным .onAwait внутри? (метод `unwrap()`)

Boris
25.01.2018
18:14:09
@relizarov Роман, подскажите, есть вообще какие-то примеры такого использования каналов? планируется ли расширять библиотеку готовыми средствами для распараллеливания идущих по каналу потоков?

Konstantin
25.01.2018
18:20:52

Boris
25.01.2018
18:21:20
тут надо было получать первый сыгравший, я начал это делать, но не добил

Sergey
25.01.2018
18:22:53

Andrew
25.01.2018
18:24:04

Boris
25.01.2018
18:25:39

Sergey
25.01.2018
18:27:46
а нельзя сделать 1 канал на несколько акторов?

Andrew
25.01.2018
18:27:50
а нельзя сделать 1 канал на несколько акторов?
actor(...) сам создаёт канал, но в теории можно сделать свой аналог, принимающий его как параметр вместо capacity:
https://github.com/Kotlin/kotlinx.coroutines/blob/ea4f2f3ac31ca7a4c80fd4afe7824b1ddf795c3c/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/channels/Actor.kt#L84

Boris
25.01.2018
18:43:46
а еще всё время хочется использовать generateSequence, но нельзя ?

Google

Boris
25.01.2018
18:44:42
причем buildSequnce тоже нельзя потому что в нем можно только его собственные саспенд-методы использовать

Sergey
25.01.2018
19:16:58
я так понимаю параллельная обработка выглядит примерно так?(если мне нужно в одном потоке это делать)
runBlocking {
val channel = Channel<Int>()
launch {
for (i in 0..20) {
channel.send(i)
}
channel.close()
}
(0..4)
.map { i ->
launch(Unconfined) {
channel.consumeEach {
delay(2000)
val thread = Thread.currentThread().name
println("$thread: i=$it coroutine=$i")
}
}
}
.forEach { it.join() }
}

Andrew
25.01.2018
19:27:00
По идее первый channel.consumeEach выгребет все данные и все i от 1 до 4 ничего не получат.

Sergey
25.01.2018
19:28:30
ну оно работает)

Andrew
25.01.2018
19:29:18
Да, delay же точка саспенда. Логично.

Sergey
25.01.2018
19:30:21
даже если убрать delay то будет работать

Andrew
25.01.2018
19:34:01
ChannelIterator.next():
> Retrieves and removes the element from this channel suspending the caller while this channel isEmpty [...]
По идее ж канал не должен успевать быть пустым. Теперь мне интересно, почему это работает, присоединюсь к ожиданию ответов.
Переключение ведь происходит не на каждом вызове suspend fun, верно?

Boris
25.01.2018
19:35:44
У меня есть прототип метода, который получает деферы по мере из выполнения, он получает все что есть в канале и пытается селектить из всех них, когда значение приходит он его из пула удаляет и повторяет селект
Но это почему-то не работает
Все что есть, в смысле все что доступно
Это обычно < capacity

Stas
25.01.2018
19:44:53
вброс: зачем вообще корутины, если есть rx?

Igor
25.01.2018
19:46:45
Народ так завелся паралельными флоу - что я уже и не знаю ?

Boris
25.01.2018
19:47:32

Stas
25.01.2018
19:48:40
саспенд внутри на тредлупе работает7

Boris
25.01.2018
19:49:39
Как асинхронный запрос в клиенте реализован это уже другой вопрос

Artem
25.01.2018
19:49:43
Ребята, а может кто-то коротко и толково изложить, что есть это "suspend"? А то я не очень понимаю

Boris
25.01.2018
19:51:06
С того места где остановился