blob: 51100e03387f6315629617fc543c980e04fca95b [file] [view]
## Streaming Calls
Dubbo-Python supports streaming calls, including `ClientStream`, `ServerStream`, and `BidirectionalStream` modes.
Streaming calls can be divided into write-streams and read-streams. For `ClientStream`, its multiple writes with a single read; for `ServerStream`, a single write with multiple reads; and `BidirectionalStream` allows multiple writes and reads.
### Write-Stream
Write operations in streaming calls can be divided into single write (`ServerStream`) and multiple writes (`ClientStream` and `BidirectionalStream`).
#### Single Write
Single write calls are similar to unary mode. For example:
```python
stub.server_stream(greeter_pb2.GreeterRequest(name="hello world from dubbo-python"))
```
#### Multiple Writes
For multiple writes, users can write data using either an iterator or `writeStream` (only one of these options should be used).
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:
```python
# Use an iterator to send multiple requests
def request_generator():
for i in ["hello", "world", "from", "dubbo-python"]:
yield greeter_pb2.GreeterRequest(name=str(i))
# Call the remote method and return a read_stream
stream = stub.client_stream(request_generator())
```
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:
```python
stream = stub.bi_stream()
# Use the write method to send messages
stream.write(greeter_pb2.GreeterRequest(name="jock"))
stream.write(greeter_pb2.GreeterRequest(name="jane"))
stream.write(greeter_pb2.GreeterRequest(name="alice"))
stream.write(greeter_pb2.GreeterRequest(name="dave"))
# Call done_writing to notify the server that the client has finished writing
stream.done_writing()
```
### Read-Stream
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:
1. The `read` method supports a `timeout` parameter (in seconds).
2. The `read` method can return one of three values: the expected data, `None` (timeout exceeded), or `EOF` (end of the read-stream).
#### Single Read
A single call to the `read` method will retrieve the data, for example:
```python
result = stream.read()
print(f"Received response: {result.message}")
```
#### Multiple Reads
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 doesnt support a timeout.
1. **Using Iterator (Recommended)**:
```python
def client_stream(self, request_iterator):
response = ""
for request in request_iterator:
print(f"Received request: {request.name}")
response += f"{request.name} "
return greeter_pb2.GreeterReply(message=response)
```
2. **Multiple Calls to `read` Method**:
```python
# Use read method to receive messages
# If no message arrives within the specified time, returns None
# If the server has finished sending messages, returns EOF
while True:
i = stream.read(timeout=0.5)
if i is dubbo.classes.EOF:
break
elif i is None:
print("No message received")
continue
print(f"Received response: {i.message}")
```