{"id":16838896,"url":"https://github.com/akarnokd/rxjavafiberinterop","last_synced_at":"2025-03-22T05:30:48.799Z","repository":{"id":38257845,"uuid":"199863706","full_name":"akarnokd/RxJavaFiberInterop","owner":"akarnokd","description":"Library for interoperation between RxJava 3 and JDK 21+ Virtual Threads","archived":false,"fork":false,"pushed_at":"2023-12-27T04:17:57.000Z","size":452,"stargazers_count":37,"open_issues_count":6,"forks_count":5,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-18T08:21:35.605Z","etag":null,"topics":["continuation","fiber","interoperation","reactive","rxjava","virtual-thread","virtual-threads"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/akarnokd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-07-31T13:39:38.000Z","updated_at":"2024-12-19T13:53:08.000Z","dependencies_parsed_at":"2023-02-10T21:16:22.963Z","dependency_job_id":"645370b4-9460-41d5-b16c-4906633b7401","html_url":"https://github.com/akarnokd/RxJavaFiberInterop","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akarnokd%2FRxJavaFiberInterop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akarnokd%2FRxJavaFiberInterop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akarnokd%2FRxJavaFiberInterop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akarnokd%2FRxJavaFiberInterop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/akarnokd","download_url":"https://codeload.github.com/akarnokd/RxJavaFiberInterop/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244912800,"owners_count":20530764,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["continuation","fiber","interoperation","reactive","rxjava","virtual-thread","virtual-threads"],"created_at":"2024-10-13T12:27:15.914Z","updated_at":"2025-03-22T05:30:46.665Z","avatar_url":"https://github.com/akarnokd.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RxJavaFiberInterop\n\nLibrary for interoperation between RxJava 3 and JDK 21's Virtual Threads (aka Fibers, Project Loom).\n\n\u003ca href='https://github.com/akarnokd/RxJavaFiberInterop/actions?query=workflow%3A%22Java+CI+with+Gradle%22'\u003e\u003cimg src='https://github.com/akarnokd/RxJavaFiberInterop/workflows/Java%20CI%20with%20Gradle/badge.svg'\u003e\u003c/a\u003e\n[![codecov.io](http://codecov.io/github/akarnokd/RxJavaFiberInterop/coverage.svg?branch=master)](http://codecov.io/github/akarnokd/RxJavaFiberInterop?branch=master)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.akarnokd/rxjava3-fiber-interop/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.akarnokd/rxjava3-fiber-interop)\n\n```groovy\n\ndependencies {\n    implementation \"com.github.akarnokd:rxjava3-fiber-interop:0.0.18\"\n}\n```\n\nRequires a JDK that has Virtual Threads as standard feature (i.e., not preview), such as [https://jdk.java.net/21/](https://jdk.java.net/21/).\n\n# Components\n\n## FiberInterop\n\n### Schedulers\n\nCurrently, the Virtual Thread API does not offer public means to specify the carrier thread(pool) thus it is not possible to use RxJava `Scheduler`s as such.\n\nYou can use the `Schedulers.from` though to convert the Fork-Join-pool backed standard Virtual Thread Executor into an RxJava `Scheduler`:\n\n```java\nvar vte = Executors.newVirtualThreadExecutor();\nScheduler vtScheduler = Schedulers.from(vte);\n\n// sometime later\nvte.close();\n```\n\nYou can then use `vtScheduler` from the example with `subscribeOn` and `observeOn` to let traditional functional callbacks to block virtually:\n\n```java\nObservable.fromCallable(() -\u003e someBlockingNetworkCall())\n.subscribeOn(vtScheduler)\n.observeOn(vtScheduler)\n.map(v -\u003e someOtherBlockingCall(v))\n.observeOn(uiThread)\n.subscribe(v -\u003e label.setText(v), e -\u003e label.setText(e.toString()));\n```\n\n:information_source: You need the special operators below to make RxJava's non-blocking backpressure into virtually blocked backpressure.\n\n### create\n\nCreates a `Flowable` from a generator callback, that can emit via `FiberEmitter`, run on an `ExecutorService` provided by the user and\nis suspended automatically upon backpressure. The callback is executed inside the virtual thread thus you can call the usual blocking APIs and get suspensions the same way.\n\nThe created `Flowable` will complete once the callback returns normally or with an error if the callback throws an exception.\n\n```java\ntry (var scope = Executors.newVirtualThreadExecutor()) {\n    FiberInterop.create(emitter -\u003e {\n        for (int i = 1; i \u003c= 5; i++) {\n             emitter.emit(1);\n        }\n    }, scope)\n    .test()\n    .awaitDone(5, TimeUnit.SECONDS)\n    .assertResult(1, 2, 3, 4, 5);\n}\n```\n\n### transform\n\nTransforms each upstream value via a callback that can emit zero or more values for each of those upstream values, run on an `ExecutorService` provided by the user and is suspended automatically upon backpressure. The callback is executed inside the virtual thread thus you can call the usual blocking APIs and get suspensions the same way.\n\n```java\ntry (var scope = Executors.newVirtualThreadExecutor()) {\n    Flowable.range(1, 5)\n    .compose(FiberInterop.transform((value, emitter) -\u003e {\n        emitter.emit(value);\n        emitter.emit(value + 1);\n    }, scope))\n    .test()\n    .awaitDone(5, TimeUnit.SECONDS)\n    .assertResult(1, 2, 2, 3, 3, 4, 4, 5, 5, 6);\n}\n```\n\n### blockingXXX\n\nRxJava uses `java.util.concurrent` locks and `CountDownLatches` via its `blockingXXX` which will automatically work within a virtual thread. Therefore, there is no need for a separate interop operator. Just block.\n\n```java\ntry (var scope = Executors.newVirtualThreadExecutor()) {\n    scope.submit(() -\u003e {\n        var v = Flowable.just(1)\n        .delay(1, TimeUnit.SECONDS)\n        .blockingLast();\n        System.out.println(v);\n    });\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakarnokd%2Frxjavafiberinterop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fakarnokd%2Frxjavafiberinterop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakarnokd%2Frxjavafiberinterop/lists"}