feat(rpc): add zio-blocks-rpc descriptor foundation (#1143)#1270
Open
987Nabil wants to merge 7 commits into
Open
feat(rpc): add zio-blocks-rpc descriptor foundation (#1143)#1270987Nabil wants to merge 7 commits into
987Nabil wants to merge 7 commits into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new zio-blocks-rpc cross-project module that can derive an RPC[T] descriptor for service traits (Scala 3 macro), and includes a reference JSON-RPC 2.0 codec/deriver plus test coverage.
Changes:
- Introduces core RPC descriptor types (
RPC,RPC.Operation, metadata) and derivation hooks (RpcDeriver,RpcFormat,ReturnTypeDecomposer,MetaAnnotation). - Implements Scala 3 macro derivation for
RPC.derived[T]. - Adds JSON-RPC reference protocol support (
JsonRpcCodec,JsonRpcDeriver,JsonRpcFormat) and Scala 3 tests + fixtures; wires module intobuild.sbt.
Reviewed changes
Copilot reviewed 16 out of 17 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| rpc/shared/src/main/scala/zio/blocks/rpc/RPC.scala | Core RPC[T] descriptor data model + derive convenience method. |
| rpc/shared/src/main/scala/zio/blocks/rpc/ReturnTypeDecomposer.scala | Type class for extracting (error, success) from return types (e.g., Either). |
| rpc/shared/src/main/scala/zio/blocks/rpc/RpcDeriver.scala | Protocol-derivation interface from RPC[T]. |
| rpc/shared/src/main/scala/zio/blocks/rpc/RpcFormat.scala | Format abstraction pairing a protocol type constructor with its deriver. |
| rpc/shared/src/main/scala/zio/blocks/rpc/annotations.scala | MetaAnnotation base for RPC trait/method annotations. |
| rpc/shared/src/main/scala/zio/blocks/rpc/jsonrpc/JsonRpcCodec.scala | JSON-RPC 2.0 request/response handler (String => String). |
| rpc/shared/src/main/scala/zio/blocks/rpc/jsonrpc/JsonRpcDeriver.scala | Builds a JsonRpcCodec[T] from an RPC[T] descriptor. |
| rpc/shared/src/main/scala/zio/blocks/rpc/jsonrpc/JsonRpcFormat.scala | RpcFormat instance for JSON-RPC. |
| rpc/shared/src/main/scala-3/zio/blocks/rpc/RPCMacros.scala | Scala 3 macro implementation for RPC.derived[T]. |
| rpc/shared/src/main/scala-3/zio/blocks/rpc/RPCCompanionVersionSpecific.scala | Scala 3 RPC.derived inline entrypoint. |
| rpc/shared/src/main/scala-3/zio/blocks/rpc/RPCVersionSpecific.scala | Scala 3 version-specific trait placeholder. |
| rpc/shared/src/main/scala-2/zio/blocks/rpc/RPCCompanionVersionSpecific.scala | Scala 2 stub (no macro derivation). |
| rpc/shared/src/main/scala-2/zio/blocks/rpc/RPCVersionSpecific.scala | Scala 2 version-specific trait placeholder. |
| rpc/shared/src/test/scala-3/zio/blocks/rpc/RPCMacroSpec.scala | Scala 3 tests for macro-derived RPC descriptors and schemas. |
| rpc/shared/src/test/scala-3/zio/blocks/rpc/fixtures/TestFixtures.scala | Test data types, annotations, and service traits used by specs. |
| rpc/shared/src/test/scala-3/zio/blocks/rpc/jsonrpc/JsonRpcIntegrationSpec.scala | JSON-RPC integration tests for request/response behavior + derivation. |
| build.sbt | Adds rpc module, hooks into test/doc aliases, sets coverage config. |
c75d578 to
6e38b80
Compare
|
🚀 Preview deployed to Netlify: https://zio-blocks-pr-1270--zio-dev.netlify.app |
4a21ee8 to
b869db7
Compare
4121640 to
3e88856
Compare
Adds a new zio-blocks-rpc module providing a derives RPC type class that captures service trait structure as a pure data representation, analogous to how derives Schema works for data types. - RPC[T] type class with Operation descriptors and Schema-backed I/O types - ReturnTypeDecomposer type class for flexible effect type support - Built-in Either[E, A] decomposition; plain types fallback to no error - MetaAnnotation for service/method/parameter-level metadata - RpcDeriver[Protocol[_]] and RpcFormat for protocol derivation - JSON-RPC 2.0 reference protocol with spec-compliant handling - Cross-compiles for Scala 2.13 + 3.x (macro derivation Scala 3 only) - 39 tests (macro derivation + JSON-RPC integration) Closes zio#1143
Comment on lines
+90
to
+98
| handle = params => { | ||
| val typedInput = operation.inputCodec.asInstanceOf[JsonCodec[Input]].decodeValue(params) | ||
| try { | ||
| handler(typedInput) | ||
| .map(output => operation.outputCodec.asInstanceOf[JsonCodec[Output]].encodeValue(output)) | ||
| } catch { | ||
| case NonFatal(error) => Left(SchemaError(error.getMessage)) | ||
| } | ||
| } |
Comment on lines
+65
to
+71
| /** | ||
| * Binds a single typed operation handler and produces an executable codec. | ||
| * | ||
| * This reference binding keeps the public API in terms of typed values plus | ||
| * the derived operation schemas/codecs, while raw JSON remains internal to | ||
| * the wire format boundary. | ||
| */ |
Comment on lines
+121
to
+123
| private[jsonrpc] | ||
| /** Internal raw JSON handler after typed binding. */ | ||
| final case class BoundOperation( |
Comment on lines
+108
to
+116
| test("MultiAnnotatedService - multiple annotations on same method") { | ||
| val rpc = RPC.derived[MultiAnnotatedService] | ||
| val op = rpc.operations(0) | ||
| assertTrue( | ||
| op.annotations.length == 2, | ||
| op.annotations.exists(_.isInstanceOf[Idempotent]), | ||
| op.annotations.exists(_.isInstanceOf[RpcDeprecated]) | ||
| ) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a new
zio-blocks-rpcmodule providing aderives RPCtype class that captures service trait structure as a pure descriptor, analogous to howderives Schemacaptures data types.Closes #1143
Design
RPC[T]captures method signatures, parameter schemas, success schemas, error schemas, and annotations at compile time. Protocol-specific artifacts derive from it viaRpcDeriver[Protocol[_]], just like codec formats derive fromSchema[A].Key Design Decisions
ReturnTypeDecomposertype class — effect/error decomposition stays extensible. Built-in support coversEither[E, A]and plain return types.MetaAnnotation— extensible annotation infrastructure for service/method metadataJsonRpcProtocol[T]contract plus a small reference binding to raw handlers for tests and lightweight integrationsWhat's Included
RPC[T]RPC.Operation[I, O]ReturnTypeDecomposer[F]MetaAnnotationRpcDeriver[Protocol[_]]RpcFormatJsonRpcProtocol[T]RPC[T]JsonRpcProtocol#bindHandlersJsonRpcCodecJsonRpcCodecModule Structure
Scope Boundary
This PR intentionally stops at the descriptor / protocol-contract layer inside blocks.
What it includes:
What it leaves for follow-up modules outside blocks: