def main(): platform = Platform() # you can register a method of a class platform.register('hello.world.1', Hi().hello, 5) # or register a function platform.register('hello.world.2', hello, 10) po = PostOffice() # demonstrate sending asynchronously. Note that key-values in the headers will be encoded as strings po.send('hello.world.1', headers={'one': 1}, body='hello world one') po.send('hello.world.2', headers={'two': 2}, body='hello world two') # demonstrate a RPC request try: result = po.request('hello.world.2', 2.0, headers={'some_key': 'some_value'}, body='hello world') if isinstance(result, EventEnvelope): print('Received RPC response:') print("HEADERS =", result.get_headers(), ", BODY =", result.get_body(), ", STATUS =", result.get_status(), ", EXEC =", result.get_exec_time(), ", ROUND TRIP =", result.get_round_trip(), "ms") except TimeoutError as e: print("Exception: ", str(e)) # illustrate parallel RPC requests event_list = list() event_list.append(EventEnvelope().set_to('hello.world.1').set_body("first request")) event_list.append(EventEnvelope().set_to('hello.world.2').set_body("second request")) try: result = po.parallel_request(event_list, 2.0) if isinstance(result, list): print('Received', len(result), 'RPC responses:') for res in result: print("HEADERS =", res.get_headers(), ", BODY =", res.get_body(), ", STATUS =", res.get_status(), ", EXEC =", res.get_exec_time(), ", ROUND TRIP =", res.get_round_trip(), "ms") except TimeoutError as e: print("Exception: ", str(e)) # connect to the network platform.connect_to_cloud() # wait until connected while not platform.cloud_ready(): try: time.sleep(0.1) except KeyboardInterrupt: # this allows us to stop the application while waiting for cloud connection platform.stop() return # Demonstrate broadcast feature # the event will be broadcast to multiple application instances that serve the same route po.broadcast("hello.world.1", body="this is a broadcast message from "+platform.get_origin()) # demonstrate deferred delivery po.send_later('hello.world.1', headers={'hello': 'world'}, body='this message arrives 5 seconds later', seconds=5.0) # # this will keep the main thread running in the background # so we can use Control-C or KILL signal to stop the application platform.run_forever()
class ObjectStreamWriter: def __init__(self, route: str): if not isinstance(route, str): raise ValueError('output stream-ID must be str') self.closed = False self.po = PostOffice() self.output_stream = route def write(self, payload: any): if not self.closed: if isinstance(payload, dict) or isinstance(payload, str) \ or isinstance(payload, bytes) \ or isinstance(payload, int) or isinstance(payload, float) or isinstance(payload, bool): # for orderly write, use RPC request to guarantee that payload is written into the object stream self.po.send(self.output_stream, headers={'type': 'data'}, body=payload) else: raise ValueError( 'payload must be dict, str, bool, int or float') def close(self): if not self.closed: self.closed = True self.po.send(self.output_stream, headers={'type': 'eof'})
def main(): platform = Platform() # register a function platform.register('hello.world', hello, 10) po = PostOffice() # demonstrate sending asynchronously. Note that key-values in the headers will be encoded as strings po.send('hello.world', headers={'one': 1}, body='hello world one') po.send('hello.world', headers={'two': 2}, body='hello world two') # demonstrate a RPC request try: result = po.request('hello.world', 2.0, headers={'some_key': 'some_value'}, body='hello world') if isinstance(result, EventEnvelope): print('Received RPC response:') print("HEADERS =", result.get_headers(), ", BODY =", result.get_body(), ", STATUS =", result.get_status(), ", EXEC =", result.get_exec_time(), ", ROUND TRIP =", result.get_round_trip(), "ms") except TimeoutError as e: print("Exception: ", str(e)) # demonstrate drop-n-forget for n in range(20): po.send('hello.world', body='just a drop-n-forget message ' + str(n)) # # this will keep the main thread running in the background # so we can use Control-C or KILL signal to stop the application platform.run_forever()
class ObjectStreamIO: STREAM_IO_MANAGER = 'object.streams.io' def __init__(self, route: str = None, expiry_seconds: int = 1800): self.platform = Platform() self.po = PostOffice() self.util = Utility() self.route = None self.input_stream = None self.output_stream = None self.eof = False self.input_closed = False self.output_closed = False if route is not None: # open an existing stream if isinstance(route, str): name: str = route if name.startswith('stream.') and '@' in name: self.route = name if self.route is None: raise ValueError('Invalid stream route') else: # create a new stream if not isinstance(expiry_seconds, int): raise ValueError('expiry_seconds must be int') result = self.po.request(self.STREAM_IO_MANAGER, 6.0, headers={ 'type': 'create', 'expiry_seconds': expiry_seconds }) if isinstance(result, EventEnvelope) and isinstance(result.get_body(), str) \ and result.get_status() == 200: name: str = result.get_body() if name.startswith('stream.') and '@' in name: self.route = name if self.route is None: raise IOError('Stream manager is not responding correctly') def get_route(self): return self.route def is_eof(self): return self.eof def read(self, timeout_seconds: float): if self.input_stream: return self.input_stream() if isinstance(timeout_seconds, int): timeout_seconds = float(timeout_seconds) if isinstance(timeout_seconds, float): # minimum read timeout is one second if timeout_seconds < 1.0: timeout_seconds = 1.0 else: raise ValueError('Read timeout must be float or int') def reader(): while not self.eof: # if input stream has nothing, it will throw TimeoutError result = self.po.request(self.route, timeout_seconds, headers={'type': 'read'}) if isinstance(result, EventEnvelope): if result.get_status() == 200: payload_type = result.get_headers().get('type') if 'eof' == payload_type: self.eof = True break if 'body' == payload_type: yield result.get_body() else: raise AppException(result.get_status(), str(result.get_body())) self.input_stream = reader return reader() def write(self, payload: any, timeout_seconds: float = 10.0): if isinstance(timeout_seconds, int): timeout_seconds = float(timeout_seconds) if isinstance(timeout_seconds, float): # minimum write timeout is five second if timeout_seconds < 5.0: timeout_seconds = 5.0 else: raise ValueError('Write timeout must be float or int') if not self.output_closed: if isinstance(payload, dict) or isinstance(payload, str) or isinstance(payload, bool) \ or isinstance(payload, int) or isinstance(payload, float): # for orderly write, use RPC request to guarantee that payload is written into the object stream self.po.request(self.route, timeout_seconds, headers={'type': 'write'}, body=payload) else: raise ValueError( 'payload must be dict, str, bool, int or float') def send_eof(self): if not self.output_closed: self.output_closed = True self.po.send(self.route, headers={'type': 'eof'}) def is_output_closed(self): return self.output_closed def get_local_streams(self): result = self.po.request(self.STREAM_IO_MANAGER, 6.0, headers={'type': 'query'}) if isinstance(result, EventEnvelope) and isinstance(result.get_body(), dict) \ and result.get_status() == 200: return result.get_body() else: return dict() def close(self): if not self.input_closed: self.input_closed = True self.po.send(self.route, headers={'type': 'close'}) def is_input_closed(self): return self.input_closed