Skip to content

Commit 8bdba77

Browse files
committed
docs: update some samples
1 parent b68376a commit 8bdba77

File tree

10 files changed

+163
-141
lines changed

10 files changed

+163
-141
lines changed

dubbo/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ def server_stream(
133133
)
134134
)
135135

136-
def bidi_stream(
136+
def bi_stream(
137137
self,
138138
method_name: str,
139139
request_serializer: Optional[SerializingFunction] = None,

dubbo/protocol/triple/call/server_call.py

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
DirectDeserializer,
4343
DirectSerializer,
4444
)
45+
from dubbo.types import RpcType, RpcTypes
4546
from dubbo.utils import FunctionHelper
4647

4748

@@ -169,18 +170,16 @@ def __init__(
169170
self,
170171
func: Callable,
171172
read_write_stream: ReadWriteStream,
172-
client_stream: bool,
173-
server_stream: bool,
173+
rpc_type: RpcType,
174174
):
175175
self._read_write_stream = read_write_stream
176176
self._func = func
177177

178-
self._is_client_stream = client_stream
179-
self._is_server_stream = server_stream
178+
self._rpc_type = rpc_type
180179

181180
def run(self) -> None:
182181
try:
183-
if not self._is_client_stream:
182+
if self._rpc_type == RpcTypes.UNARY.value:
184183
result = self._func(self._read_write_stream.read())
185184
else:
186185
result = self._func(self._read_write_stream)
@@ -196,15 +195,15 @@ def handle_result(self, result: Any) -> None:
196195
if not self._read_write_stream.can_write_more():
197196
return
198197

199-
if not self._is_server_stream:
198+
if not self._rpc_type.server_stream:
200199
# get single result
201200
self._read_write_stream.write(result)
202-
self._read_write_stream.done_writing()
203201
else:
204202
# get multi results
205203
for message in result:
206204
self._read_write_stream.write(message)
207-
self._read_write_stream.done_writing()
205+
206+
self._read_write_stream.done_writing()
208207
except Exception as e:
209208
self.handle_exception(e)
210209

@@ -240,11 +239,9 @@ def create(
240239
"""
241240

242241
method_descriptor = method_handler.method_descriptor
243-
rpc_type = method_descriptor.get_rpc_type()
244242

245243
return DefaultMethodRunner(
246244
method_descriptor.get_method(),
247245
read_write_stream,
248-
rpc_type.client_stream,
249-
rpc_type.server_stream,
246+
method_descriptor.get_rpc_type(),
250247
)

samples/serialization/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ SerializingFunction = Callable[..., bytes]
1313

1414
For deserialization functions, we specify:
1515

16-
```
16+
```python
1717
# A function that takes an argument of type bytes and returns data of any type
1818
DeserializingFunction = Callable[[bytes], Any]
1919
```

samples/stream/README.md

Lines changed: 76 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,94 @@
11
## Streaming Calls
22

3-
Dubbo-python supports streaming calls, including `ClientStream`, `ServerStream`, and `BidirectionalStream`. The key difference in these calls is the use of iterators: passing an iterator as a parameter for `ClientStream`, receiving an iterator for `ServerStream`, or both passing and receiving iterators for `BidirectionalStream`.
3+
Dubbo-Python supports streaming calls, including `ClientStream`, `ServerStream`, and `BidirectionalStream` modes.
44

5-
When using `BidirectionalStream`, the client needs to pass an iterator as a parameter to send multiple data points, while also receiving an iterator to handle multiple responses from the server.
5+
Streaming calls can be divided into write-streams and read-streams. For `ClientStream`, it’s multiple writes with a single read; for `ServerStream`, a single write with multiple reads; and `BidirectionalStream` allows multiple writes and reads.
66

7-
Here’s an example of the client-side code:
7+
### Write-Stream
8+
9+
Write operations in streaming calls can be divided into single write (`ServerStream`) and multiple writes (`ClientStream` and `BidirectionalStream`).
10+
11+
#### Single Write
12+
13+
Single write calls are similar to unary mode. For example:
814

915
```python
10-
class GreeterServiceStub:
11-
def __init__(self, client: dubbo.Client):
12-
self.bidi_stream = client.bidi_stream(
13-
method_name="biStream",
14-
request_serializer=greeter_pb2.GreeterRequest.SerializeToString,
15-
response_deserializer=greeter_pb2.GreeterReply.FromString,
16-
)
16+
stub.server_stream(greeter_pb2.GreeterRequest(name="hello world from dubbo-python"))
17+
```
1718

18-
def bi_stream(self, values):
19-
return self.bidi_stream(values)
19+
#### Multiple Writes
2020

21+
For multiple writes, users can write data using either an iterator or `writeStream` (only one of these options should be used).
2122

22-
if __name__ == "__main__":
23-
reference_config = ReferenceConfig.from_url(
24-
"tri://127.0.0.1:50051/org.apache.dubbo.samples.proto.Greeter"
25-
)
26-
dubbo_client = dubbo.Client(reference_config)
23+
1. **Iterator-based Write**: Writing via iterator is similar to unary mode, with the main difference being the use of an iterator for multiple writes. For example:
2724

28-
stub = GreeterServiceStub(dubbo_client)
25+
```python
26+
# Use an iterator to send multiple requests
27+
def request_generator():
28+
for i in ["hello", "world", "from", "dubbo-python"]:
29+
yield greeter_pb2.GreeterRequest(name=str(i))
2930

30-
# Iterator of request
31-
def request_generator():
32-
for item in ["hello", "world", "from", "dubbo-python"]:
33-
yield greeter_pb2.GreeterRequest(name=str(item))
31+
# Call the remote method and return a read_stream
32+
stream = stub.client_stream(request_generator())
33+
```
3434

35-
result = stub.bi_stream(request_generator())
35+
2. **Using `writeStream`**: This method requires an empty argument, after which data is written incrementally using `write`, and `done_writing` is called to end the write-stream. For example:
3636

37-
for i in result:
38-
print(f"Received response: {i.message}")
39-
```
37+
```python
38+
stream = stub.bi_stream()
39+
# Use the write method to send messages
40+
stream.write(greeter_pb2.GreeterRequest(name="jock"))
41+
stream.write(greeter_pb2.GreeterRequest(name="jane"))
42+
stream.write(greeter_pb2.GreeterRequest(name="alice"))
43+
stream.write(greeter_pb2.GreeterRequest(name="dave"))
44+
# Call done_writing to notify the server that the client has finished writing
45+
stream.done_writing()
46+
```
4047

41-
And here’s the server-side code:
48+
### Read-Stream
49+
50+
Read operations for streaming calls can be single read (`ClientStream`) or multiple reads (`ServerStream` and `BidirectionalStream`). A `ReadStream` is returned in all cases, and data can be read using the `read` method or an iterator. When using `read`, please note:
51+
52+
1. The `read` method supports a `timeout` parameter (in seconds).
53+
2. The `read` method can return one of three values: the expected data, `None` (timeout exceeded), or `EOF` (end of the read-stream).
54+
55+
#### Single Read
56+
57+
A single call to the `read` method will retrieve the data, for example:
4258

4359
```python
44-
def bi_stream(request_stream):
45-
for request in request_stream:
46-
print(f"Received message from {request.name}")
47-
yield greeter_pb2.GreeterReply(message=request.name)
48-
49-
50-
if __name__ == "__main__":
51-
# build a method handler
52-
method_handler = RpcMethodHandler.bi_stream(
53-
bi_stream,
54-
request_deserializer=greeter_pb2.GreeterRequest.FromString,
55-
response_serializer=greeter_pb2.GreeterReply.SerializeToString,
56-
)
57-
# build a service handler
58-
service_handler = RpcServiceHandler(
59-
service_name="org.apache.dubbo.samples.data.Greeter",
60-
method_handlers={"biStream": method_handler},
61-
)
62-
63-
service_config = ServiceConfig(service_handler)
64-
65-
# start the server
66-
server = dubbo.Server(service_config).start()
67-
68-
input("Press Enter to stop the server...\n")
60+
result = stream.read()
61+
print(f"Received response: {result.message}")
6962
```
7063

64+
#### Multiple Reads
65+
66+
Multiple reads can be done by repeatedly calling `read`, with handling for `None` and `EOF` values. Since `ReadStream` implements `__iter__` and `__next__`, an iterator-based approach can also be used, which automatically handles these values but doesn’t support a timeout.
67+
68+
1. **Using Iterator (Recommended)**:
69+
70+
```python
71+
def client_stream(self, request_iterator):
72+
response = ""
73+
for request in request_iterator:
74+
print(f"Received request: {request.name}")
75+
response += f"{request.name} "
76+
return greeter_pb2.GreeterReply(message=response)
77+
```
78+
79+
2. **Multiple Calls to `read` Method**:
80+
81+
```python
82+
# Use read method to receive messages
83+
# If no message arrives within the specified time, returns None
84+
# If the server has finished sending messages, returns EOF
85+
while True:
86+
i = stream.read(timeout=0.5)
87+
if i is dubbo.classes.EOF:
88+
break
89+
elif i is None:
90+
print("No message received")
91+
continue
92+
print(f"Received response: {i.message}")
93+
```
94+

samples/stream/bidi_stream/client.py

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@
1717
import dubbo
1818
from dubbo.classes import EOF
1919
from dubbo.configs import ReferenceConfig
20-
from samples.data import greeter_pb2
20+
from samples.proto import greeter_pb2
2121

2222

2323
class GreeterServiceStub:
2424
def __init__(self, client: dubbo.Client):
25-
self.bidi_stream = client.bidi_stream(
25+
self.bidi_stream = client.bi_stream(
2626
method_name="biStream",
2727
request_serializer=greeter_pb2.GreeterRequest.SerializeToString,
2828
response_deserializer=greeter_pb2.GreeterReply.FromString,
@@ -33,42 +33,30 @@ def bi_stream(self, *args):
3333

3434

3535
if __name__ == "__main__":
36+
# Create a reference config
3637
reference_config = ReferenceConfig.from_url(
3738
"tri://127.0.0.1:50051/org.apache.dubbo.samples.data.Greeter"
3839
)
3940
dubbo_client = dubbo.Client(reference_config)
40-
4141
stub = GreeterServiceStub(dubbo_client)
4242

43-
# # Iterator of request
44-
# def request_generator():
45-
# for item in ["hello", "world", "from", "dubbo-python"]:
46-
# yield greeter_pb2.GreeterRequest(name=str(item))
47-
#
48-
# result = stub.bi_stream(request_generator())
49-
#
50-
# for i in result:
51-
# print(f"Received response: {i.message}")
52-
5343
stream = stub.bi_stream()
44+
# use write method to send message
45+
stream.write(greeter_pb2.GreeterRequest(name="jock"))
5446

55-
stream.write(greeter_pb2.GreeterRequest(name="hello"))
56-
57-
# print(f"Received response: {stream.read().message}")
47+
# use read method to receive message
48+
print(f"Received response: {stream.read().message}")
5849

59-
stream.write(greeter_pb2.GreeterRequest(name="world"))
60-
stream.write(greeter_pb2.GreeterRequest(name="from"))
61-
stream.write(greeter_pb2.GreeterRequest(name="dubbo-python"))
50+
# continue to send message
51+
stream.write(greeter_pb2.GreeterRequest(name="jane"))
52+
stream.write(greeter_pb2.GreeterRequest(name="alice"))
53+
stream.write(greeter_pb2.GreeterRequest(name="dave"))
54+
# done_writing method must be called to notify the server that the client has finished writing
6255
stream.done_writing()
6356

64-
# 直接调用read方法
65-
print(stream.read())
66-
67-
# 迭代器调用read方法(推荐)
68-
for i in stream:
69-
print(f"Received response: {i.message}")
70-
71-
# 循环调用read方法
57+
# use read method to receive message
58+
# If no message arrives within the specified time, returns None
59+
# If the server has finished sending messages and the client has received all messages, returns EOF
7260
while True:
7361
i = stream.read(timeout=0.5)
7462
if i is EOF:

samples/stream/bidi_stream/server.py

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,32 +16,43 @@
1616
import dubbo
1717
from dubbo.configs import ServiceConfig
1818
from dubbo.proxy.handlers import RpcMethodHandler, RpcServiceHandler
19-
from samples.data import greeter_pb2
19+
from samples.proto import greeter_pb2
2020

2121
import time
2222

2323

24-
def bi_stream(request_stream):
25-
for request in request_stream:
26-
print(f"Received message from {request.name}")
27-
yield greeter_pb2.GreeterReply(message=request.name)
28-
time.sleep(1)
24+
class GreeterServiceServicer:
25+
def bi_stream(self, stream):
26+
counter = 0
27+
for request in stream:
28+
print(f"Received request: {request.name}")
29+
# simulate a long time to process
30+
if counter == 1:
31+
time.sleep(1)
32+
counter += 1
2933

34+
stream.write(greeter_pb2.GreeterReply(message=f"Hello, {request.name}!"))
3035

31-
if __name__ == "__main__":
32-
# build a method handler
36+
stream.done_writing()
37+
38+
39+
def build_server_handler():
3340
method_handler = RpcMethodHandler.bi_stream(
34-
bi_stream,
41+
GreeterServiceServicer().bi_stream,
3542
method_name="biStream",
3643
request_deserializer=greeter_pb2.GreeterRequest.FromString,
3744
response_serializer=greeter_pb2.GreeterReply.SerializeToString,
3845
)
39-
# build a service handler
4046
service_handler = RpcServiceHandler(
4147
service_name="org.apache.dubbo.samples.data.Greeter",
4248
method_handlers=[method_handler],
4349
)
50+
return service_handler
4451

52+
53+
if __name__ == "__main__":
54+
# build a service config
55+
service_handler = build_server_handler()
4556
service_config = ServiceConfig(service_handler, host="127.0.0.1", port=50051)
4657

4758
# start the server

samples/stream/client_stream/client.py

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# limitations under the License.
1616
import dubbo
1717
from dubbo.configs import ReferenceConfig
18-
from samples.data import greeter_pb2
18+
from samples.proto import greeter_pb2
1919

2020

2121
class GreeterServiceStub:
@@ -26,31 +26,23 @@ def __init__(self, client: dubbo.Client):
2626
response_deserializer=greeter_pb2.GreeterReply.FromString,
2727
)
2828

29-
def client_stream(self, *args):
30-
return self.unary_stream(args)
29+
def client_stream(self, request_iterator):
30+
return self.unary_stream(request_iterator)
3131

3232

3333
if __name__ == "__main__":
3434
reference_config = ReferenceConfig.from_url(
3535
"tri://127.0.0.1:50051/org.apache.dubbo.samples.data.Greeter"
3636
)
3737
dubbo_client = dubbo.Client(reference_config)
38-
3938
stub = GreeterServiceStub(dubbo_client)
4039

41-
# 迭代器方法
40+
# use iterator to send multiple requests
4241
def request_generator():
4342
for i in ["hello", "world", "from", "dubbo-python"]:
4443
yield greeter_pb2.GreeterRequest(name=str(i))
4544

45+
# call the remote method and return a read_stream
4646
stream = stub.client_stream(request_generator())
47-
print(stream.read())
48-
49-
# stream 调用方法
50-
stream = stub.client_stream()
51-
for i in ["hello", "world", "from", "dubbo-python"]:
52-
stream.write(greeter_pb2.GreeterRequest(name=str(i)))
53-
54-
stream.done_writing()
55-
47+
# use read method to get the response
5648
print(stream.read())

0 commit comments

Comments
 (0)