This is an automated email from the ASF dual-hosted git repository.
chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory-site.git
The following commit(s) were added to refs/heads/main by this push:
new a5c564a0b1 🔄 synced local 'docs/compiler/' with remote 'docs/compiler/'
a5c564a0b1 is described below
commit a5c564a0b1eeb70a8e8fb08d81088a47728571d5
Author: chaokunyang <[email protected]>
AuthorDate: Thu May 21 08:45:04 2026 +0000
🔄 synced local 'docs/compiler/' with remote 'docs/compiler/'
---
docs/compiler/compiler-guide.md | 13 +++++++
docs/compiler/flatbuffers-idl.md | 21 ++++++++++++
docs/compiler/generated-code.md | 58 +++++++++++++++++++++++++++++++
docs/compiler/index.md | 45 +++++++++++++++++++-----
docs/compiler/protobuf-idl.md | 22 ++++++++++--
docs/compiler/schema-idl.md | 74 ++++++++++++++++++++++++++++++++++++++--
6 files changed, 218 insertions(+), 15 deletions(-)
diff --git a/docs/compiler/compiler-guide.md b/docs/compiler/compiler-guide.md
index 7339a2e909..cfa7dd547f 100644
--- a/docs/compiler/compiler-guide.md
+++ b/docs/compiler/compiler-guide.md
@@ -72,6 +72,7 @@ Compile options:
| `--swift_namespace_style` | Swift namespace style: `enum` or
`flatten` | `enum` |
| `--emit-fdl` | Emit translated FDL (for non-FDL
inputs) | `false` |
| `--emit-fdl-path` | Write translated FDL to this path
(file or directory) | (stdout) |
+| `--grpc` | Generate gRPC service companions for
Java and Python | `false` |
Schema-level file options are supported for language-specific generation
choices.
For `go_nested_type_style` and `swift_namespace_style`, the CLI flag overrides
@@ -146,6 +147,18 @@ foryc user.fdl order.fdl product.fdl --output ./generated
foryc compiler/examples/service.fdl --java_out=./generated/java
--python_out=./generated/python
```
+**Generate Java and Python gRPC service companions:**
+
+```bash
+foryc compiler/examples/service.fdl --java_out=./generated/java
--python_out=./generated/python --grpc
+```
+
+The generated gRPC service code uses Fory to serialize request and response
+payloads. Java output imports grpc-java APIs and Python output imports `grpc`;
+applications that compile or run those generated service files must provide
+their own gRPC dependencies. Fory's Java and Python runtime packages do not
add a
+hard gRPC dependency for this feature.
+
**Use import search paths:**
```bash
diff --git a/docs/compiler/flatbuffers-idl.md b/docs/compiler/flatbuffers-idl.md
index 90600640b4..e57d1c8a4d 100644
--- a/docs/compiler/flatbuffers-idl.md
+++ b/docs/compiler/flatbuffers-idl.md
@@ -122,6 +122,27 @@ message Container {
}
```
+### Services
+
+FlatBuffers `rpc_service` definitions are translated to Fory services. With
+`--grpc`, the compiler emits Java and Python gRPC service companions that use
+Fory serialization for request and response payloads.
+
+```fbs
+rpc_service SearchService {
+ Lookup(SearchRequest):SearchResponse;
+ StreamLookup(SearchRequest):SearchResponse (streaming: "server");
+}
+```
+
+```bash
+foryc api.fbs --java_out=./generated/java --python_out=./generated/python
--grpc
+```
+
+Generated service code imports grpc APIs, so applications must provide
grpc-java
+or `grpcio` dependencies when they compile or run those files. The Fory runtime
+packages do not add gRPC as a hard dependency.
+
### Defaults and Metadata
- FlatBuffers default values are parsed but not applied as Fory runtime
defaults.
diff --git a/docs/compiler/generated-code.md b/docs/compiler/generated-code.md
index 520dda8d3b..beee9cf15d 100644
--- a/docs/compiler/generated-code.md
+++ b/docs/compiler/generated-code.md
@@ -238,6 +238,32 @@ byte[] data = person.toBytes();
Person restored = Person.fromBytes(data);
```
+### gRPC Service Companions
+
+When a schema contains services and the compiler is run with `--grpc`, Java
+generation emits one `<ServiceName>Grpc.java` file per service next to the
model
+types.
+
+```java
+public final class AddressBookServiceGrpc {
+ public static final String SERVICE_NAME = "addressbook.AddressBookService";
+
+ public static AddressBookServiceStub newStub(io.grpc.Channel channel) { ... }
+ public static AddressBookServiceBlockingStub newBlockingStub(io.grpc.Channel
channel) { ... }
+ public static AddressBookServiceFutureStub newFutureStub(io.grpc.Channel
channel) { ... }
+
+ public abstract static class AddressBookServiceImplBase
+ implements io.grpc.BindableService {
+ public void lookup(Person request,
io.grpc.stub.StreamObserver<AddressBook> responseObserver) { ... }
+ }
+}
+```
+
+The generated marshaller serializes each request or response with the schema
+module's `ThreadSafeFory`. It uses grpc-java's `MethodDescriptor.Marshaller`
+API, so applications compiling these files must provide grpc-java dependencies.
+Those dependencies are not added to Fory Java runtime artifacts.
+
## Python
### Output Layout
@@ -337,6 +363,38 @@ data = person.to_bytes()
restored = Person.from_bytes(data)
```
+### gRPC Service Companions
+
+When a schema contains services and the compiler is run with `--grpc`, Python
+generation emits a companion module named `<module>_grpc.py`. The module name
is
+derived from the Fory package by replacing dots with underscores, or
`generated`
+when the schema has no package.
+
+```python
+class AddressBookServiceStub:
+ def __init__(self, channel):
+ self.lookup = channel.unary_unary(
+ "/addressbook.AddressBookService/Lookup",
+ request_serializer=_serialize,
+ response_deserializer=_deserialize,
+ )
+
+
+class AddressBookServiceServicer:
+ def lookup(self, request, context):
+ raise NotImplementedError("Method not implemented!")
+
+
+def add_servicer(servicer, server): ...
+```
+
+Python gRPC serializers receive and return complete `bytes` payloads, so the
+generated callbacks call the model module's `_get_fory().serialize(...)` and
+`_get_fory().deserialize(...)` directly. Applications using the generated
+companion module must install `grpcio`; `pyfory` does not add a hard gRPC
+dependency. The Python API uses snake_case method names while preserving the
+original IDL method names in the gRPC wire paths.
+
## Rust
### Output Layout
diff --git a/docs/compiler/index.md b/docs/compiler/index.md
index 8f516ec7ab..0b227d7e2a 100644
--- a/docs/compiler/index.md
+++ b/docs/compiler/index.md
@@ -22,7 +22,9 @@ license: |
Fory IDL is a schema definition language for Apache Fory that enables type-safe
cross-language serialization. Define your data structures once and generate
native data structure code for Java, Python, Go, Rust, C++, C#, Swift,
-JavaScript, Dart, Scala, and Kotlin.
+JavaScript, Dart, Scala, and Kotlin. Fory IDL can also describe RPC services;
+for Java and Python, the compiler can generate gRPC service companions that use
+Fory serialization for request and response payloads.
## Example Schema
@@ -70,8 +72,32 @@ union Animal [id=106] {
Dog dog = 1;
Cat cat = 2;
}
+
+message LookupRequest [id=107] {
+ string name = 1;
+}
+
+message LookupResponse [id=108] {
+ Animal animal = 1;
+}
+
+service AnimalService {
+ rpc Lookup (LookupRequest) returns (LookupResponse);
+ rpc Classify (Animal) returns (Animal);
+}
+```
+
+Generate Java and Python models plus gRPC service companions with:
+
+```bash
+foryc animals.fdl --java_out=./generated/java --python_out=./generated/python
--grpc
```
+The generated service code uses normal gRPC APIs, but request and response
+objects are serialized with Fory. Applications provide their own grpc-java or
+`grpcio` dependencies; Fory runtime packages do not add gRPC as a hard
+dependency.
+
## Why Fory IDL?
### Schema-First Development
@@ -170,14 +196,15 @@ data = bytes(person) # or `person.to_bytes()`
## Documentation
-| Document | Description
|
-| ----------------------------------------------- |
------------------------------------------------- |
-| [Fory IDL Syntax](schema-idl.md) | Complete language syntax
and grammar |
-| [Type System](schema-idl.md#type-system) | Primitive types,
collections, and type rules |
-| [Compiler Guide](compiler-guide.md) | CLI options and build
integration |
-| [Generated Code](generated-code.md) | Output format for each
target language |
-| [Protocol Buffers IDL Support](protobuf-idl.md) | Protobuf mapping rules and
adoption guidance |
-| [FlatBuffers IDL Support](flatbuffers-idl.md) | FlatBuffers mapping rules
and codegen differences |
+| Document | Description
|
+| ------------------------------------------------ |
------------------------------------------------- |
+| [Fory IDL Syntax](schema-idl.md) | Complete language syntax
and grammar |
+| [Type System](schema-idl.md#type-system) | Primitive types,
collections, and type rules |
+| [RPC Services](schema-idl.md#service-definition) | Service and RPC method
syntax |
+| [Compiler Guide](compiler-guide.md) | CLI options and build
integration |
+| [Generated Code](generated-code.md) | Output format for each
target language |
+| [Protocol Buffers IDL Support](protobuf-idl.md) | Protobuf mapping rules
and adoption guidance |
+| [FlatBuffers IDL Support](flatbuffers-idl.md) | FlatBuffers mapping rules
and codegen differences |
## Key Concepts
diff --git a/docs/compiler/protobuf-idl.md b/docs/compiler/protobuf-idl.md
index 0105a89558..3a13fb8ff4 100644
--- a/docs/compiler/protobuf-idl.md
+++ b/docs/compiler/protobuf-idl.md
@@ -49,10 +49,13 @@ how protobuf concepts map to Fory, and how to use
protobuf-only Fory extension o
| Circular refs | Not supported | Supported
|
| Unknown fields | Preserved | Not preserved
|
| Generated types | Protobuf-specific model types | Native language
constructs |
-| gRPC ecosystem | Native | In progress (active
development) |
+| gRPC ecosystem | Native | Java/Python service
codegen |
-Fory gRPC support is under active development. For production gRPC
-workflows today, protobuf remains the mature/default choice.
+Fory can generate Java and Python gRPC service companions with `--grpc`. Those
+services use normal gRPC transports but serialize request and response payloads
+with Fory rather than protobuf. For broad gRPC ecosystem tooling, schema
+reflection, and protobuf-native interceptors, protobuf remains the
mature/default
+choice.
## Why Use Apache Fory
@@ -307,6 +310,19 @@ modifiers (and optional `ref(weak=true)` where needed).
Replace protobuf generation steps with the Fory compiler invocation for target
languages.
+For Java and Python services, add `--grpc` to emit gRPC companion code:
+
+```bash
+foryc api.proto --java_out=./generated/java --python_out=./generated/python
--grpc
+```
+
+Generated Java service files compile against grpc-java, and generated Python
+service modules import `grpc`. Add those dependencies in your application
build;
+Fory runtime packages do not add gRPC as a hard dependency. Protobuf `oneof`
+fields are translated to Fory union fields inside request and response
messages.
+Direct union RPC request or response types are not part of normal protobuf RPC
+syntax.
+
### Step 5: Run Compatibility Checks
For staged transitions, keep both formats in parallel and verify payload-level
diff --git a/docs/compiler/schema-idl.md b/docs/compiler/schema-idl.md
index 799b8fb0ee..8b5835faaf 100644
--- a/docs/compiler/schema-idl.md
+++ b/docs/compiler/schema-idl.md
@@ -34,6 +34,7 @@ An Fory IDL file typically consists of:
2. Optional file-level options
3. Optional import statements
4. Type definitions (enums, messages, and unions)
+5. Optional service definitions
```protobuf
// Optional package declaration
@@ -48,8 +49,14 @@ import "common/types.fdl";
// Type definitions
enum Color [id=100] { ... }
message User [id=101] { ... }
-message Order [id=102] { ... }
-union Event [id=103] { ... }
+message OrderRequest [id=102] { ... }
+message Order [id=103] { ... }
+union Event [id=104] { ... }
+
+// Service definitions
+service OrderService {
+ rpc GetOrder (OrderRequest) returns (Order);
+}
```
## Comments
@@ -876,6 +883,62 @@ union_def := 'union' IDENTIFIER [type_options] '{'
union_field* '}'
union_field := field_type IDENTIFIER '=' INTEGER ';'
```
+## Service Definition
+
+Services define RPC method contracts in Fory IDL. They are optional: schemas
+with services still generate the normal data model types, and gRPC service code
+is generated only when the compiler is run with `--grpc` for Java or Python.
+
+```protobuf
+message GetPetRequest [id=200] {
+ string name = 1;
+}
+
+message PetRecord [id=201] {
+ string name = 1;
+ Animal animal = 2;
+}
+
+service PetDirectory {
+ rpc GetPet (GetPetRequest) returns (PetRecord);
+ rpc Classify (Animal) returns (Animal);
+}
+```
+
+The first method uses message request and response types. The second method
uses
+a direct union request and response type, which is supported in Fory IDL.
+
+### Streaming RPCs
+
+Use `stream` before the request type, the response type, or both:
+
+```protobuf
+service PetDirectory {
+ rpc GetPet (GetPetRequest) returns (PetRecord); // unary
+ rpc WatchPets (GetPetRequest) returns (stream PetRecord); // server
streaming
+ rpc ImportPets (stream PetRecord) returns (PetRecord); // client
streaming
+ rpc ChatPets (stream Animal) returns (stream Animal); //
bidirectional streaming
+}
+```
+
+### RPC Type Rules
+
+- Request and response types must reference named message or union types.
+- Enum, primitive, collection, map, and array types are not valid direct RPC
+ request or response types. Wrap those values in a message when they are part
+ of a service contract.
+- The generated Java and Python gRPC companions use Fory serialization for each
+ RPC payload. Applications that compile or run those companions provide their
+ own grpc-java or `grpcio` dependency.
+
+**Grammar:**
+
+```
+service_def := 'service' IDENTIFIER '{' rpc_method* '}'
+rpc_method := 'rpc' IDENTIFIER '(' ['stream'] named_type ')'
+ 'returns' '(' ['stream'] named_type ')' ';'
+```
+
## Field Definition
Fields define the properties of a message.
@@ -1570,7 +1633,7 @@ For protobuf-specific extension options and `(fory).`
syntax, see
## Grammar Summary
```
-file := [package_decl] file_option* import_decl* type_def*
+file := [package_decl] file_option* import_decl* definition*
package_decl := 'package' package_name ['alias' package_name] ';'
package_name := IDENTIFIER ('.' IDENTIFIER)*
@@ -1580,6 +1643,7 @@ option_name := IDENTIFIER
import_decl := 'import' STRING ';'
+definition := type_def | service_def
type_def := enum_def | message_def | union_def
enum_def := 'enum' IDENTIFIER [type_options] '{' enum_body '}'
@@ -1593,6 +1657,10 @@ field_def := [modifiers] field_type IDENTIFIER '='
INTEGER [field_options] ';
union_def := 'union' IDENTIFIER [type_options] '{' union_field* '}'
union_field := ['repeated'] field_type IDENTIFIER '=' INTEGER [field_options]
';'
+
+service_def := 'service' IDENTIFIER '{' rpc_method* '}'
+rpc_method := 'rpc' IDENTIFIER '(' ['stream'] named_type ')'
+ 'returns' '(' ['stream'] named_type ')' ';'
option_value := 'true' | 'false' | IDENTIFIER | INTEGER | STRING
reserved_stmt := 'reserved' reserved_items ';'
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]