Skip to content

Move suspend/reactive route validation to processor#12539

Open
yawkat wants to merge 4 commits into
5.0.xfrom
fix-11131-suspend-flow-guard
Open

Move suspend/reactive route validation to processor#12539
yawkat wants to merge 4 commits into
5.0.xfrom
fix-11131-suspend-flow-guard

Conversation

@yawkat
Copy link
Copy Markdown
Member

@yawkat yawkat commented Mar 20, 2026

Summary

  • add a compile-time route validation rule for suspended controller methods that declare reactive or async return types
  • make RouteValidationVisitor recognize Kotlin/KSP route methods where HttpMethodMapping is exposed as a stereotype rather than a direct annotation
  • remove the runtime guard from DefaultRouteInfo
  • extend the Kotlin test harness so tests can opt into additional KSP symbol processor providers
  • add a focused end-to-end Kotlin compile test that exercises RouteValidationVisitor through a narrow route-only visitor provider

Why

Issue #11131 reproduces a bad failure mode when a suspended controller method returns a reactive type after prior suspension. Rather than rejecting that shape during route construction at runtime, this change moves the unsupported-signature check into the existing http-validation processor path so developers get earlier feedback.

Implementation details

  • SuspendedReactiveReturnTypeRule now checks the declared suspended method return type and explicitly rejects kotlinx.coroutines.flow.Flow in addition to other async/reactive types
  • RouteValidationVisitor now falls back to stereotype-aware lookup for HttpMethodMapping, which is necessary for Kotlin/KSP route methods annotated with @Get
  • inject-kotlin-test now supports opt-in extra KSP SymbolProcessorProviders without changing default behavior for existing tests
  • the end-to-end test uses a narrow route-only provider built on TypeElementSymbolProcessor, avoiding unrelated service-loaded visitors from polluting the test path

Verification

Targeted end-to-end verification passes with:

./gradlew :micronaut-inject-kotlin:test --tests io.micronaut.kotlin.processing.visitor.SuspendedReactiveRouteValidationSpec \
  :micronaut-inject-kotlin-test:compileGroovy \
  :micronaut-http-validation:compileJava \
  :micronaut-router:compileJava

Results:

  • suspend fun hello(): String compiles
  • suspend fun hello(): Flow<String> fails during KSP/visitor processing with:
    • Unsupported suspended controller return type [kotlinx.coroutines.flow.Flow]. Suspend functions must not return reactive or async types.

Notes

  • this PR intentionally removes the earlier runtime guard in favor of processor-based validation
  • the Kotlin test harness change is additive: existing helper behavior remains unchanged unless a test explicitly opts into extra symbol processor providers

Fixes #11131

yawkat and others added 2 commits March 20, 2026 08:29
Fixes #11131

Co-Authored-By: multicode <multicode@yawk.at>
Fixes #11131

Co-Authored-By: multicode <multicode@yawk.at>
@yawkat yawkat changed the title Reject suspended reactive controller return types Move suspend/reactive route validation to processor Mar 20, 2026
Fixes #11131

Co-Authored-By: multicode <multicode@yawk.at>
@yawkat yawkat requested a review from dstepanov March 20, 2026 09:30
@yawkat yawkat marked this pull request as ready for review March 20, 2026 09:30
@yawkat yawkat marked this pull request as draft March 20, 2026 09:32
Co-Authored-By: multicode <multicode@yawk.at>
@sonarqubecloud
Copy link
Copy Markdown

@yawkat yawkat marked this pull request as ready for review March 20, 2026 10:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

COROUTINE_SUSPENDED response when calling coroutine in a suspending controller function which returns Flow

2 participants