Pull to refresh

Comments 6

Огромное спасибо за статью! Замечательная подача тех. материала и литературный дар.
Если есть возможность, пожалуйста, продолжайте!
Спасибо за статью. Было бы интересно почитать о том как отрефакторить существующий код под новый реактивный манер. Например вот интересно различные подходы конвертации итеративного метода (возвращающего список объектов) так чтобы он возвращал Flux. Должен ли этот новый метод создавать поток чтобы сабмитать новые объекты (hot stream), или же этот метод должен только оборачивать список объектов в Flux (и вызывать метод complete)?
Не до конца понял вопрос, но попробую ответить. Какого-то универсального рецепта нет, все упирается в данные. Если метод возвращает весь необходимый список объектов единовременно (не потоком) — вероятно это не Flux, а Mono. Hot Stream это скорее про какие-нибудь Event Listener на UI или системные ивенты, вебсокеты. Что-то, вызов чего мы не контролируем.

Вот конкретный пример. Есть некий итеративный метод который возвращает список найденных блютус устройств: List<DiscoveredDevice> getDiscoveredDevices(). Каждый вызов этого метода может возвратить разные устройства. Необходимо отрефакторить данный метод так чтобы он стал реактивным, а именно, чтоб он возвращал нескончаемый поток, так чтобы клиенты могли бы подписаться на этот поток, и соответственно, получать новые устройства. Первое что приходит в голову это — Flux<DiscoveredDevice> getDiscoveredDevicesStream(), где внутри этого метода создается поток (thread), и по мере обнаружения новых устройств, вызывался бы emitter.next(...). Однако кажется мне что создание потока не совсем верное решение, ибо в reactor'е есть столько различный способов работы с потоками, что может быть это можно как-то решить с помощью reactor'а? Кроме того, может быть лучше работу с потоком возложить на клиента этого метода? Спасибо.

Если хотите бесконечный поток данных (push based), то я не вижу другого выхода. Кто-то ведь должен вызывать emitter.next у FluxSink. С точки зрения реактора можно воспользоваться шедулером.

Вариант проще — pull based подход через fluxSink.onRequest. Тут и нить выполнения можно изменить через subscribeOn. Правда, в этом случае сложно организовать «бесконечную» работу.

Более элегантного варианта я не знаю, благо есть гиттер, где в т.ч. отвечают оперативней.
Бесконечный поток данных может генерироваться либо потоком (thread), либо актором. Актор — это возобновляемая асинхронная процедура, и требует для своей работы Executor'a, который неизбежно в себе содержит thread'ы, так что совсем без thread'ов обойтись все равно не удастся. Единственным преимуществом асинхронного программирования (неважно в какой форме — Reactor, JavaRx, Akka actors, Kotlin korutines) является то, что один Executor с ограниченным числом потоков может обслужить любое количество асинхронных процедур. Это единственный выход, если таких акторов/процедур у вас миллионы, предпочительный, если тысячи, и лишняя головная боль, если их единицы или десятки. Я не думаю, что сведения о новых обнаруженных устройствах нужны миллионам обработчиков, так что спокойно пользуйтесь потоками и забудьте про Reactor. Асинхронные библитеки еще не достигли той степени зрелости, как средства многопоточности (которым потребовалось на это 33 года, от изобретения семаформа до выпуска первой версии Java). В этих библиотеках здравые идеи перемешаны с мусором, недопониманием, и выпячиванием функционального подхода в ущерб объектно-ориентированному. В этой каше интересно ковыряться, но если вам нужен результат, а не удовлетворенное любопытство, то овчинка не стоит выделки.
Only those users with full accounts are able to leave comments. Log in, please.