Skip to content

Commit 466d178

Browse files
committed
updated guide examples
1 parent fae813f commit 466d178

File tree

16 files changed

+247
-97
lines changed

16 files changed

+247
-97
lines changed

examples/tutorial/reactivex/chat_client.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,12 @@ async def list_channels(self) -> List[str]:
147147
).pipe(operators.map(lambda _: utf8_decode(_.data)),
148148
operators.to_list())
149149

150+
async def list_channel_users(self, channel_name: str) -> List[str]:
151+
request = Payload(ensure_bytes(channel_name), composite(route('channel.users')))
152+
return await ReactiveXClient(self._rsocket).request_stream(
153+
request
154+
).pipe(operators.map(lambda _: utf8_decode(_.data)),
155+
operators.to_list())
150156

151157
async def main():
152158
connection1 = await asyncio.open_connection('localhost', 6565)
@@ -174,16 +180,21 @@ async def messaging_example(user1, user2):
174180
user1.listen_for_messages()
175181
user2.listen_for_messages()
176182

177-
await user1.join('channel1')
178-
await user2.join('channel1')
183+
channel_name = 'channel1'
184+
await user1.join(channel_name)
185+
await user2.join(channel_name)
179186

180187
print(f'Channels: {await user1.list_channels()}')
188+
print(f'Channel {channel_name} users: {await user1.list_channel_users(channel_name)}')
181189

182190
await user1.private_message('user2', 'private message from user1')
183-
await user1.channel_message('channel1', 'channel message from user1')
191+
await user1.channel_message(channel_name, 'channel message from user1')
184192

185193
await asyncio.sleep(1)
186194

195+
await user1.leave(channel_name)
196+
print(f'Channel {channel_name} users: {await user1.list_channel_users(channel_name)}')
197+
187198
user1.stop_listening_for_messages()
188199
user2.stop_listening_for_messages()
189200

examples/tutorial/reactivex/chat_server.py

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
from examples.tutorial.reactivex.shared import (Message, chat_filename_mimetype, ClientStatistics,
1515
ServerStatisticsRequest, ServerStatistics, dataclass_to_payload,
16-
decode_dataclass)
16+
decode_dataclass, decode_payload)
1717
from rsocket.extensions.composite_metadata import CompositeMetadata
1818
from rsocket.extensions.helpers import composite, metadata_item
1919
from rsocket.frame_helpers import ensure_bytes
@@ -36,15 +36,15 @@ class SessionId(str): # allow weak reference
3636
@dataclass()
3737
class UserSessionData:
3838
username: str
39-
session_id: str
39+
session_id: SessionId
4040
messages: Queue = field(default_factory=Queue)
4141
statistics: Optional[ClientStatistics] = None
4242
requested_statistics: ServerStatisticsRequest = field(default_factory=ServerStatisticsRequest)
4343

4444

4545
@dataclass(frozen=True)
4646
class ChatData:
47-
channel_users: Dict[str, Set[str]] = field(default_factory=lambda: defaultdict(WeakSet))
47+
channel_users: Dict[str, Set[SessionId]] = field(default_factory=lambda: defaultdict(WeakSet))
4848
files: Dict[str, bytes] = field(default_factory=dict)
4949
channel_messages: Dict[str, Queue] = field(default_factory=lambda: defaultdict(Queue))
5050
user_session_by_id: Dict[str, UserSessionData] = field(default_factory=WeakValueDictionary)
@@ -95,6 +95,13 @@ def new_statistics_data(requested_statistics: ServerStatisticsRequest):
9595
return ServerStatistics(**statistics_data)
9696

9797

98+
def find_username_by_session(session_id: SessionId) -> Optional[str]:
99+
session = chat_data.user_session_by_id.get(session_id)
100+
if session is None:
101+
return None
102+
return session.username
103+
104+
98105
class ChatUserSession:
99106

100107
def __init__(self):
@@ -105,11 +112,10 @@ def remove(self):
105112
del chat_data.user_session_by_id[self._session.session_id]
106113

107114
def router_factory(self):
108-
router = RequestRouter()
115+
router = RequestRouter(payload_mapper=decode_payload)
109116

110117
@router.response('login')
111-
async def login(payload: Payload) -> Observable:
112-
username = utf8_decode(payload.data)
118+
async def login(username: str) -> Observable:
113119
logging.info(f'New user: {username}')
114120
session_id = SessionId(uuid.uuid4())
115121
self._session = UserSessionData(username, session_id)
@@ -118,15 +124,13 @@ async def login(payload: Payload) -> Observable:
118124
return reactivex.just(Payload(ensure_bytes(session_id)))
119125

120126
@router.response('channel.join')
121-
async def join_channel(payload: Payload) -> Observable:
122-
channel_name = utf8_decode(payload.data)
127+
async def join_channel(channel_name: str) -> Observable:
123128
ensure_channel_exists(channel_name)
124129
chat_data.channel_users[channel_name].add(self._session.session_id)
125130
return reactivex.empty()
126131

127132
@router.response('channel.leave')
128-
async def leave_channel(payload: Payload) -> Observable:
129-
channel_name = utf8_decode(payload.data)
133+
async def leave_channel(channel_name: str) -> Observable:
130134
chat_data.channel_users[channel_name].discard(self._session.session_id)
131135
return reactivex.empty()
132136

@@ -157,10 +161,17 @@ async def get_channels() -> Observable:
157161
return reactivex.from_iterable(
158162
(Payload(ensure_bytes(channel)) for channel in chat_data.channel_messages.keys()))
159163

160-
@router.fire_and_forget('statistics')
161-
async def receive_statistics(payload: Payload):
162-
statistics = decode_dataclass(payload.data, ClientStatistics)
164+
@router.stream('channel.users')
165+
async def get_channel_users(channel_name: str) -> Observable:
166+
if channel_name not in chat_data.channel_users:
167+
return reactivex.empty()
163168

169+
return reactivex.from_iterable(Payload(ensure_bytes(find_username_by_session(session_id))) for
170+
session_id in
171+
chat_data.channel_users[channel_name])
172+
173+
@router.fire_and_forget('statistics')
174+
async def receive_statistics(statistics: ClientStatistics):
164175
logging.info('Received client statistics. memory usage: %s', statistics.memory_usage)
165176

166177
self._session.statistics = statistics
@@ -198,9 +209,7 @@ def on_next(payload: Payload):
198209
limit_rate=2)
199210

200211
@router.response('message')
201-
async def send_message(payload: Payload) -> Observable:
202-
message = decode_dataclass(payload.data, Message)
203-
212+
async def send_message(message: Message) -> Observable:
204213
logging.info('Received message for user: %s, channel: %s', message.user, message.channel)
205214

206215
target_message = Message(self._session.username, message.content, message.channel)

examples/tutorial/reactivex/shared.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,14 @@ def dataclass_to_payload(obj) -> Payload:
4747

4848
def decode_dataclass(data: bytes, cls: Type[T]) -> T:
4949
return cls(**json.loads(utf8_decode(data)))
50+
51+
52+
def decode_payload(cls, payload: Payload):
53+
data = payload.data
54+
55+
if cls is bytes:
56+
return data
57+
if cls is str:
58+
return utf8_decode(data)
59+
60+
return decode_dataclass(data, cls)

examples/tutorial/step4/chat_client.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ async def list_channels(self) -> List[str]:
7777
response = await AwaitableRSocket(self._rsocket).request_stream(request)
7878
return list(map(lambda _: utf8_decode(_.data), response))
7979

80+
async def list_channel_users(self, channel_name: str):
81+
request = Payload(ensure_bytes(channel_name), composite(route('channel.users')))
82+
response = await AwaitableRSocket(self._rsocket).request_stream(request)
83+
return list(map(lambda _: utf8_decode(_.data), response))
84+
8085

8186
async def main():
8287
connection1 = await asyncio.open_connection('localhost', 6565)
@@ -100,16 +105,22 @@ async def messaging_example(user1: ChatClient, user2: ChatClient):
100105
user1.listen_for_messages()
101106
user2.listen_for_messages()
102107

103-
await user1.join('channel1')
104-
await user2.join('channel1')
108+
channel_name = 'channel1'
109+
110+
await user1.join(channel_name)
111+
await user2.join(channel_name)
105112

106113
print(f'Channels: {await user1.list_channels()}')
114+
print(f'Channel {channel_name} users: {await user1.list_channel_users(channel_name)}')
107115

108116
await user1.private_message('user2', 'private message from user1')
109-
await user1.channel_message('channel1', 'channel message from user1')
117+
await user1.channel_message(channel_name, 'channel message from user1')
110118

111119
await asyncio.sleep(1)
112120

121+
await user1.leave(channel_name)
122+
print(f'Channel {channel_name} users: {await user1.list_channel_users(channel_name)}')
123+
113124
user1.stop_listening_for_messages()
114125
user2.stop_listening_for_messages()
115126

examples/tutorial/step5/chat_client.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,6 @@ async def leave(self, channel_name: str):
3838
await self._rsocket.request_response(request)
3939
return self
4040

41-
async def get_users(self, channel_name: str) -> List[str]:
42-
request = Payload(ensure_bytes(channel_name), composite(route('channel.users')))
43-
users = await AwaitableRSocket(self._rsocket).request_stream(request)
44-
return [utf8_decode(user.data) for user in users]
45-
4641
def listen_for_messages(self):
4742
def print_message(data: bytes):
4843
message = decode_dataclass(data, Message)
@@ -97,6 +92,11 @@ async def list_channels(self) -> List[str]:
9792
response = await AwaitableRSocket(self._rsocket).request_stream(request)
9893
return list(map(lambda _: utf8_decode(_.data), response))
9994

95+
async def list_channel_users(self, channel_name: str):
96+
request = Payload(ensure_bytes(channel_name), composite(route('channel.users')))
97+
response = await AwaitableRSocket(self._rsocket).request_stream(request)
98+
return list(map(lambda _: utf8_decode(_.data), response))
99+
100100

101101
async def main():
102102
connection1 = await asyncio.open_connection('localhost', 6565)
@@ -129,15 +129,15 @@ async def messaging_example(user1: ChatClient, user2: ChatClient):
129129
await user2.join(channel_name)
130130

131131
print(f'Channels: {await user1.list_channels()}')
132-
print(f'Channel {channel_name} users: {await user1.get_users(channel_name)}')
132+
print(f'Channel {channel_name} users: {await user1.list_channel_users(channel_name)}')
133133

134134
await user1.private_message('user2', 'private message from user1')
135135
await user1.channel_message(channel_name, 'channel message from user1')
136136

137137
await asyncio.sleep(1)
138138

139139
await user1.leave(channel_name)
140-
print(f'Channel {channel_name} users: {await user1.get_users(channel_name)}')
140+
print(f'Channel {channel_name} users: {await user1.list_channel_users(channel_name)}')
141141

142142
user1.stop_listening_for_messages()
143143
user2.stop_listening_for_messages()

examples/tutorial/step5/chat_server.py

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
from more_itertools import first
1111

12-
from examples.tutorial.step5.shared import (Message, chat_filename_mimetype, dataclass_to_payload, decode_dataclass)
12+
from examples.tutorial.step5.shared import (Message, chat_filename_mimetype, dataclass_to_payload, decode_payload)
1313
from reactivestreams.publisher import DefaultPublisher, Publisher
1414
from reactivestreams.subscriber import Subscriber
1515
from reactivestreams.subscription import DefaultSubscription
@@ -95,11 +95,10 @@ def remove(self):
9595
del chat_data.user_session_by_id[self._session.session_id]
9696

9797
def router_factory(self):
98-
router = RequestRouter()
98+
router = RequestRouter(payload_mapper=decode_payload)
9999

100100
@router.response('login')
101-
async def login(payload: Payload) -> Awaitable[Payload]:
102-
username = utf8_decode(payload.data)
101+
async def login(username: str) -> Awaitable[Payload]:
103102
logging.info(f'New user: {username}')
104103
session_id = SessionId(uuid.uuid4())
105104
self._session = UserSessionData(username, session_id)
@@ -108,22 +107,18 @@ async def login(payload: Payload) -> Awaitable[Payload]:
108107
return create_response(ensure_bytes(session_id))
109108

110109
@router.response('channel.join')
111-
async def join_channel(payload: Payload) -> Awaitable[Payload]:
112-
channel_name = utf8_decode(payload.data)
110+
async def join_channel(channel_name: str) -> Awaitable[Payload]:
113111
ensure_channel_exists(channel_name)
114112
chat_data.channel_users[channel_name].add(self._session.session_id)
115113
return create_response()
116114

117115
@router.response('channel.leave')
118-
async def leave_channel(payload: Payload) -> Awaitable[Payload]:
119-
channel_name = utf8_decode(payload.data)
116+
async def leave_channel(channel_name: str) -> Awaitable[Payload]:
120117
chat_data.channel_users[channel_name].discard(self._session.session_id)
121118
return create_response()
122119

123120
@router.stream('channel.users')
124-
async def get_channel_users(payload: Payload) -> Publisher:
125-
channel_name = utf8_decode(payload.data)
126-
121+
async def get_channel_users(channel_name: str) -> Publisher:
127122
if channel_name not in chat_data.channel_users:
128123
return EmptyStream()
129124

@@ -160,9 +155,7 @@ async def get_channels() -> Publisher:
160155
return StreamFromGenerator(lambda: generator)
161156

162157
@router.response('message')
163-
async def send_message(payload: Payload) -> Awaitable[Payload]:
164-
message = decode_dataclass(payload.data, Message)
165-
158+
async def send_message(message: Message) -> Awaitable[Payload]:
166159
logging.info('Received message for user: %s, channel: %s', message.user, message.channel)
167160

168161
target_message = Message(self._session.username, message.content, message.channel)

examples/tutorial/step5/shared.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,14 @@ def dataclass_to_payload(obj) -> Payload:
3030

3131
def decode_dataclass(data: bytes, cls: Type[T]) -> T:
3232
return cls(**json.loads(utf8_decode(data)))
33+
34+
35+
def decode_payload(cls, payload: Payload):
36+
data = payload.data
37+
38+
if cls is bytes:
39+
return data
40+
if cls is str:
41+
return utf8_decode(data)
42+
43+
return decode_dataclass(data, cls)

examples/tutorial/step6/chat_client.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ async def list_channels(self) -> List[str]:
139139
response = await AwaitableRSocket(self._rsocket).request_stream(request)
140140
return list(map(lambda _: utf8_decode(_.data), response))
141141

142+
async def list_channel_users(self, channel_name: str):
143+
request = Payload(ensure_bytes(channel_name), composite(route('channel.users')))
144+
response = await AwaitableRSocket(self._rsocket).request_stream(request)
145+
return list(map(lambda _: utf8_decode(_.data), response))
146+
142147

143148
async def main():
144149
connection1 = await asyncio.open_connection('localhost', 6565)
@@ -162,20 +167,26 @@ async def main():
162167
await files_example(user1, user2)
163168

164169

165-
async def messaging_example(user1, user2):
170+
async def messaging_example(user1: ChatClient, user2: ChatClient):
166171
user1.listen_for_messages()
167172
user2.listen_for_messages()
168173

169-
await user1.join('channel1')
170-
await user2.join('channel1')
174+
channel_name = 'channel1'
175+
176+
await user1.join(channel_name)
177+
await user2.join(channel_name)
171178

172179
print(f'Channels: {await user1.list_channels()}')
180+
print(f'Channel {channel_name} users: {await user1.list_channel_users(channel_name)}')
173181

174182
await user1.private_message('user2', 'private message from user1')
175-
await user1.channel_message('channel1', 'channel message from user1')
183+
await user1.channel_message(channel_name, 'channel message from user1')
176184

177185
await asyncio.sleep(1)
178186

187+
await user1.leave(channel_name)
188+
print(f'Channel {channel_name} users: {await user1.list_channel_users(channel_name)}')
189+
179190
user1.stop_listening_for_messages()
180191
user2.stop_listening_for_messages()
181192

0 commit comments

Comments
 (0)