Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable use of Kotlin Flow as return value #954

Closed
rstoyanchev opened this issue Apr 18, 2024 · 7 comments
Closed

Enable use of Kotlin Flow as return value #954

rstoyanchev opened this issue Apr 18, 2024 · 7 comments
Assignees
Labels
type: enhancement A general enhancement
Milestone

Comments

@rstoyanchev
Copy link
Contributor

Using ReactiveAdapterRegistry when handling return values from annotated controller methods such as @SchemaMapping, @BatchMapping, and @GraphQlExceptionHandler would enable use of Kotlin's Flow.

@rstoyanchev rstoyanchev added the type: enhancement A general enhancement label Apr 18, 2024
@rstoyanchev rstoyanchev added this to the 1.3.0 milestone Apr 18, 2024
@rstoyanchev rstoyanchev self-assigned this Apr 18, 2024
@hantsy
Copy link
Contributor

hantsy commented Apr 19, 2024

Also need to enable Flow in Subscription, and batch data loader(instead of CompletableFuture).

@koenpunt
Copy link
Contributor

koenpunt commented Apr 19, 2024

@hantsy batch data loader already works with Monos, so you could use the mono {} helper from kotlinx.coroutines.reactor, e.g.;

registry.forName<UUID, Merchant>("merchantDataLoader").registerMappedBatchLoader { merchantIds, _ ->
    mono {
        merchantService.findAllById(merchantIds).associateBy { it.id }
    }
}

Or for a method returning a flow, it can be returned as Flux;

registry.forName<UUID, Merchant>("merchantDataLoader").registerBatchLoader { merchantIds, _ ->
    merchantService.findAllById(merchantIds).asFlux()
}

@rstoyanchev
Copy link
Contributor Author

@SubscriptionMapping is just a shortcut annotation for @SchemaMapping(typeName="subscription"), but I confirm it will support subscriptions.

@hantsy
Copy link
Contributor

hantsy commented May 28, 2024

I tried to update my example project to use Flow.

@QueryMapping
fun allPosts(): Flow<Post> = postService.allPosts()// remove .toList() to return Flow type directly

But run the following tests in the QueryTests.

@Test
  fun `get all posts`() = runTest {
      coEvery { postService.allPosts() } returns
              flowOf(
                  Post(
                      id = UUID.randomUUID(),
                      title = "Post 1",
                      content = "Post 1 content",
                      status = PostStatus.DRAFT,
                      createdAt = LocalDateTime.now()
                  ),
                  Post(
                      id = UUID.randomUUID(),
                      title = "Post 2",
                      content = "Post 2 content",
                      status = PostStatus.DRAFT,
                      createdAt = LocalDateTime.now()
                  )
              )
      val query = "{ allPosts { title content }}"
//         graphQlTester.document(query).execute()
//             .errors().satisfy { it.forEach { error -> log.debug("error message: ${error.message}") } }
      graphQlTester.document(query)
         .execute()
         .path("data.allPosts[*].title")
         .entityList(String::class.java).hasSize(2).contains("POST 1", "POST 2")

      coVerify(exactly = 1) { postService.allPosts() }
  }

And I got the error [TypeMismatchError{path=[allPosts], expectedType=[Post!]}].

The example project here: https://github.com/hantsy/spring-graphql-sample/tree/master/spring-graphql-rsocket-kotlin-co

@koenpunt
Copy link
Contributor

@hantsy is your postService.getPosts() defined as suspend fun? Then that might be the problem, because returning a flow doesn't require the method to be a suspend fun, only the consumer of the flow needs to be in a coroutine context.

@hantsy
Copy link
Contributor

hantsy commented May 29, 2024

Created an new issue for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

3 participants