Sergey Morgunov
11/06/2019, 7:30 PM@FunctionalInterface
public interface ServiceCall<Request, Response> {
CompletionStage<Response> invoke(Request request);
}
В принципе нет никакой проблемы использовать это и в Kotlin, но всё-таки это не Kotlin way, где есть корутины и suspend
функции.
Вопрос: Могу ли я разово написать какой-то Kotlin extension к этой библиотеке, в котором будет свой KServiceCall
с методом
suspend fun invoke(request: Request ): Response;
И чтобы везде, где на вход требуется оригинальный ServiceCall
, я передавал уже свой KServiceCall
?miha-x64
11/06/2019, 8:20 PMrunBlocking
? 😀Bogdan
11/06/2019, 9:24 PMServiceCall
- java интерфейс то можно сделать так
// класс который нужно расширить
class Foo {
fun <Request, Response> async(f: ServiceCall<Request, Response>) {}
}
fun <Request, Response> Foo.async(f: suspend (Request) -> Response) {
// GlobalScope для примера
async(ServiceCall<Request, Response> { GlobalScope.async { f(it) }.asCompletableFuture() })
}
fun main() {
val foo = Foo()
foo.async<String, Int> { it.toInt() }
}
Bogdan
11/06/2019, 9:29 PMfun <Request, Response> Foo.async(f: suspend (Request) -> Response) {
val callBack = object : ServiceCall<Request, Response> {
override fun invoke(request: Request): CompletionStage<Response> {
return GlobalScope.async { f(request) }.asCompletableFuture()
}
}
async(callBack)
}
Bogdan
11/06/2019, 9:29 PMSergey Morgunov
11/06/2019, 9:43 PMBogdan
11/06/2019, 9:59 PMSergey Morgunov
11/06/2019, 10:11 PMgildor
11/06/2019, 11:27 PMKonstantin Petrukhnov
11/07/2019, 6:04 AMSergey Morgunov
11/07/2019, 9:11 AMGlobalScope.future
это нормально? Я возможно не так понял документацию, но у меня сложилось ощущение, что каждая корутина из GlobalScope осядет в хипе и умрёт только вместе с приложение. Из чего я делаю вывод, что если я на каждый HTTP запрос будут дергать GlobalScope.future
, то OOM мне обеспечен быстрее, чем я смогу что-либо понять 🙂 В реальности нужна корутина (со всеми её чилдами) только на обработку HTTP запроса и хотелось бы, чтобы её жизненный цикл закончился вместе с жизненным циклом запроса (=по завершению метода, в котором корутина родилась)Sergey Morgunov
11/07/2019, 9:15 AMsuspend
метод, из которого пользователь может без проблем вызывать другие suspend
методы и не париться.gildor
11/07/2019, 10:48 AMgildor
11/07/2019, 10:50 AMgildor
11/07/2019, 10:55 AMSergey Morgunov
11/07/2019, 12:11 PMДа, вы …К чёрту формальности, лучше на ты 😄
Лучше конечно иметь специальный скоуп со своим жизненным циклом, но если просто создать скоуп и никогда его не отменять это ничем не отличается от GlobalScopeСпасибо за комментарий! 👍 Я почему-то после прочтения был уверен, что контекст корутины из хипа не пропадёт, так как на него будет ссылка из синглтона GlobalScope, жизненный цикл которого равен жизненному циклу приложения.
Судя по оригинальному интерфейсу не понятно зачем нужны врапперы, там же возвращается CompletionStage и на него уже есть адаптер, просто вызвать await()Возможно не совсем корректно сформулировал. Дело в том, что нам нужно не вызывать этот метод, а реализовывать. Т.е. по коду разбросаны десятки анонимных имплементаций этого интерфейса (в виде лямбд конечно). И в этих имплементациях классические вермишели из thenApply.thenApply.thenCombile и тому подобное. Хочется всё это переписать на корутины. При этом так, чтобы на месте текущих Java лямбд
return request -> {
// this return CompletableFuture
}
появилось что-то вроде
return serviceCall {
// this I can call suspend functions
}