Skip to content

Conversation

Mr3zee
Copy link
Member

@Mr3zee Mr3zee commented Aug 4, 2025

One thing that doesn't work: proto source sets

@Mr3zee Mr3zee requested a review from bjhham August 4, 2025 17:14
@Mr3zee Mr3zee self-assigned this Aug 4, 2025
Copy link
Contributor

coderabbitai bot commented Aug 4, 2025

Walkthrough

This change introduces initial support for a gRPC plugin for Ktor using kotlinx-rpc. It adds version properties, a manifest file, a proto definition, generated stubs, a sample service implementation, application integration, documentation, version mapping, and a test verifying end-to-end gRPC functionality.

Changes

Cohort / File(s) Change Summary
Version Properties and Mapping
plugins/gradle.properties, plugins/server/org.jetbrains/kotlinx-rpc-grpc/versions.ktor.yaml
Added a version property for kotlinx-rpc-grpc and new version mapping for dependencies required by the gRPC plugin.
Manifest and Documentation
plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/manifest.ktor.yaml, plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/documentation.md
Introduced a manifest file and documentation describing usage, configuration, and installation instructions for the gRPC plugin.
Proto and Generated Stubs
plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/proto/service.proto, plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/stub.kt
Added a proto definition for SampleService and generated corresponding Kotlin data classes and service interface.
Service Implementation and App Integration
plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/SampleServiceImpl.kt, plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/inside_app.kt
Added a sample implementation of the service and integrated it with a Ktor application via an extension function.
Testing
plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/test.kt
Added a test class to verify the gRPC service with a real client/server interaction.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15–20 minutes

Suggested reviewers

  • bjhham

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (8)
plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/inside_app.kt (1)

5-9: Consider using a more descriptive function name.

The function name install() is generic and could be confusing since Ktor already has a built-in install function for features/plugins. Consider a more specific name like installGrpcSample() or configureGrpcService().

-fun Application.install() {
+fun Application.installGrpcSample() {
     grpc {
         registerService<SampleService> { SampleServiceImpl() }
     }
 }

The gRPC service registration logic itself looks correct for kotlinx-rpc integration.

plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/SampleServiceImpl.kt (1)

1-5: Consider renaming the parameter for clarity.

The parameter name name followed by property access name.name could be confusing. Consider using a more descriptive parameter name.

-    override suspend fun greeting(name: ClientGreeting): ServerGreeting {
-        return ServerGreeting { content = "Hello, ${name.name}!" }
+    override suspend fun greeting(request: ClientGreeting): ServerGreeting {
+        return ServerGreeting { content = "Hello, ${request.name}!" }
     }

The service implementation logic is correct and follows the expected pattern for kotlinx-rpc services.

plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/test.kt (1)

12-17: Consider using dynamic port allocation to avoid conflicts.

The hard-coded port 8081 could cause test failures if the port is already in use. Consider using a dynamic port or testApplication's built-in port management.

-        application {
-            grpc(8081) {
-                registerService<SampleService> { SampleServiceImpl() }
-            }
-        }
+        application {
+            grpc {
+                registerService<SampleService> { SampleServiceImpl() }
+            }
+        }

Then retrieve the actual port from the application for the client connection.

plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/manifest.ktor.yaml (2)

8-10: Address the Amper support limitation.

The TODO comment indicates that Amper support is disabled pending fixes. Consider documenting this limitation more prominently for users who might expect Amper support.

Would you like me to help create a more detailed explanation of the Amper limitation in the documentation or add it to a known issues section?


29-38: Clarify proto source set structure intention.

The commented sections suggest uncertainty about the proto file structure. This aligns with the PR objective noting that "proto source sets do not currently work." Consider either removing these comments or converting them to a clear TODO with an issue reference.

-# I need src/main/proto structure
-#
-#mainSourceSet:
-#  - proto/service.proto
-
-# Or Maybe?
-#src:
-#  - main:
-#      - proto:
-#          - proto/service.proto
+# TODO: Add support for proto source sets (see issue reference)
+# Planned structure:
+# mainSourceSet:
+#   - proto/service.proto
plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/stub.kt (2)

3-9: Consider using immutable data classes for better design.

The current implementation uses mutable properties, which can lead to unexpected side effects. Consider making the data classes immutable for better thread safety and predictability.

-class ClientGreeting {
-    var name: String = ""
-
-    companion object {
-        operator fun invoke(body: ClientGreeting.() -> Unit): ClientGreeting = ClientGreeting().apply(body)
-    }
-}
+data class ClientGreeting(
+    val name: String = ""
+) {
+    companion object {
+        operator fun invoke(body: ClientGreetingBuilder.() -> Unit): ClientGreeting {
+            return ClientGreetingBuilder().apply(body).build()
+        }
+    }
+}
+
+class ClientGreetingBuilder {
+    var name: String = ""
+    fun build() = ClientGreeting(name)
+}

11-17: Apply the same immutability improvement to ServerGreeting.

Similar to ClientGreeting, ServerGreeting should also be immutable for consistency and better design practices.

-class ServerGreeting {
-    var content: String = ""
-
-    companion object {
-        operator fun invoke(body: ServerGreeting.() -> Unit): ServerGreeting = ServerGreeting().apply(body)
-    }
-}
+data class ServerGreeting(
+    val content: String = ""
+) {
+    companion object {
+        operator fun invoke(body: ServerGreetingBuilder.() -> Unit): ServerGreeting {
+            return ServerGreetingBuilder().apply(body).build()
+        }
+    }
+}
+
+class ServerGreetingBuilder {
+    var content: String = ""
+    fun build() = ServerGreeting(content)
+}
plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/documentation.md (1)

34-34: Fix redundant phrasing as flagged by static analysis.

The phrase "alongside with" is redundant. Use either "alongside" or "with".

-The `SampleService` interface will generated for you alongside with other types and helper declarations.
+The `SampleService` interface will be generated for you alongside other types and helper declarations.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b90ed4e and ebb1c0e.

📒 Files selected for processing (9)
  • plugins/gradle.properties (1 hunks)
  • plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/SampleServiceImpl.kt (1 hunks)
  • plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/documentation.md (1 hunks)
  • plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/inside_app.kt (1 hunks)
  • plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/manifest.ktor.yaml (1 hunks)
  • plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/proto/service.proto (1 hunks)
  • plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/stub.kt (1 hunks)
  • plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/test.kt (1 hunks)
  • plugins/server/org.jetbrains/kotlinx-rpc-grpc/versions.ktor.yaml (1 hunks)
🧰 Additional context used
🪛 Buf (1.55.1)
plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/proto/service.proto

3-3: Files with package "io.ktor" must be within a directory "io/ktor" relative to root but were in directory "plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/proto".

(PACKAGE_DIRECTORY_MATCH)

🪛 LanguageTool
plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/documentation.md

[style] ~34-~34: This phrase is redundant. Consider writing “alongside” or “with”.
Context: ...rvice` interface will generated for you alongside with other types and helper declarations. ...

(ALONGSIDE_WITH)

🔇 Additional comments (7)
plugins/gradle.properties (1)

6-6: LGTM! Version property added for the new gRPC plugin.

The version format 0.10.0-grpc-121 suggests this might be a pre-release or specialized build. Ensure this version is stable and available in the intended repository.

plugins/server/org.jetbrains/kotlinx-rpc-grpc/versions.ktor.yaml (1)

1-4: LGTM — gRPC plugin dependency versions verified

  • The version mapping for Ktor "[3.0,)" correctly targets Ktor 3.0+
  • org.jetbrains.kotlinx:kotlinx-rpc-grpc-ktor-server:$kotlinx-rpc-grpc properly references the Gradle property
  • io.grpc:grpc-netty:1.73.0 and io.grpc:grpc-kotlin-stub:1.4.1 were confirmed on Maven Central

No further changes required.

plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/proto/service.proto (2)

3-3: Consider the package directory structure.

The static analysis tool correctly identifies that package io.ktor should typically be placed in directory io/ktor relative to the proto root. While this might be acceptable for the plugin registry structure, it could cause issues with standard Protocol Buffer tooling and code generation.

Consider whether this directory structure aligns with the project's proto conventions and tooling requirements.


5-15: LGTM! Proto definition is well-structured.

The Protocol Buffers definition correctly uses proto3 syntax and defines appropriate message types and service contract. The field numbering and RPC method signature are properly structured for gRPC communication.

plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/stub.kt (1)

19-21: LGTM for the service interface design.

The SampleService interface correctly uses a suspend function, which is appropriate for gRPC operations that are inherently asynchronous.

plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/documentation.md (2)

5-11: LGTM for the comprehensive disclaimer.

The disclaimer appropriately sets expectations about the dev preview status and encourages community feedback through multiple channels.


69-69: Unable to locate client cleanup methods – please verify consistency

I wasn’t able to find any close(), shutdown() or awaitTermination() methods on the generated gRPC client in the repository. Before we update the docs, please manually confirm how your greeterClient(…) (or other RPC client factory) actually exposes its shutdown API:

  • Verify the return type of your greeterClient() (or equivalent) function:
    • If it implements AutoCloseable/Closeable, using client.close() in the docs is correct.
    • If it returns a raw gRPC channel (e.g., ManagedChannel), you’ll need to use client.shutdown() followed by client.awaitTermination(...).
  • Once you’ve confirmed the real API, update documentation.md (line 69) to match the client’s actual cleanup methods.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/proto/service.proto (1)

9-11: Field numbering gap is harmless but unconventional

content starts at field #2, leaving #1 unused. While legal, keeping numbering dense avoids confusion for future schema evolution.

- string content = 2;
+ string content = 1;

If #1 is intentionally reserved, add an explicit reserved 1; statement.

plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/documentation.md (1)

34-34: Fix grammar and remove redundant phrasing

-The `SampleService` interface will generated for you alongside with other types and helper declarations. 
+The `SampleService` interface will be generated for you alongside other types and helper declarations.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ebb1c0e and b31d6e4.

📒 Files selected for processing (9)
  • plugins/gradle.properties (1 hunks)
  • plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/SampleServiceImpl.kt (1 hunks)
  • plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/documentation.md (1 hunks)
  • plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/inside_app.kt (1 hunks)
  • plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/manifest.ktor.yaml (1 hunks)
  • plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/proto/service.proto (1 hunks)
  • plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/stub.kt (1 hunks)
  • plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/test.kt (1 hunks)
  • plugins/server/org.jetbrains/kotlinx-rpc-grpc/versions.ktor.yaml (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/stub.kt
🚧 Files skipped from review as they are similar to previous changes (6)
  • plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/SampleServiceImpl.kt
  • plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/inside_app.kt
  • plugins/server/org.jetbrains/kotlinx-rpc-grpc/versions.ktor.yaml
  • plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/test.kt
  • plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/manifest.ktor.yaml
  • plugins/gradle.properties
🧰 Additional context used
🪛 LanguageTool
plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/documentation.md

[style] ~34-~34: This phrase is redundant. Consider writing “alongside” or “with”.
Context: ...rvice` interface will generated for you alongside with other types and helper declarations. ...

(ALONGSIDE_WITH)

🪛 Buf (1.55.1)
plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/proto/service.proto

3-3: Files with package "io.ktor" must be within a directory "io/ktor" relative to root but were in directory "plugins/server/org.jetbrains/kotlinx-rpc-grpc/3.0/proto".

(PACKAGE_DIRECTORY_MATCH)

Comment on lines +26 to +37
sources:
- SampleServiceImpl.kt

# I need src/main/proto structure
#
#mainSourceSet:
# - proto/service.proto

# Or Maybe?
#src:
# - main:
# - proto:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm updating it so you can just write:

sources:
  - SampleServiceImpl.kt
  - service.proto

And it'll move the proto file into its own source folder.

Copy link
Member Author

@Mr3zee Mr3zee Sep 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bjhham is this solution much easier than to make custom source mapping?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, custom source mappings would need a bit of extra work to ensure they play nice with the gradle vs. amper source folder layout logic. The new project templating engine I'm working on will have support for all that though.

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.

2 participants