Example #1
0
 def send_keep_alive(self):
     message = "Keep-Alive " + self.util.get_iso_8601(time.time(),
                                                      show_ms=True)
     envelope = EventEnvelope()
     envelope.set_to(self.OUTGOING_WS_PATH).set_header(
         'type', 'text').set_body(message)
     self.platform.send_event(envelope)
Example #2
0
 def exists(self, routes: any):
     if isinstance(routes, str):
         single_route = routes
         if self.has_route(single_route):
             return True
         if self.cloud_ready():
             event = EventEnvelope()
             event.set_to(self.SERVICE_QUERY).set_header(
                 'type', 'find').set_header('route', single_route)
             result = self.request(event, 8.0)
             if isinstance(result, EventEnvelope):
                 if result.get_body() is not None:
                     return result.get_body()
     if isinstance(routes, list):
         if len(routes) > 0:
             remote_routes = list()
             for r in routes:
                 if not self.platform.has_route(r):
                     remote_routes.append(r)
             if len(remote_routes) == 0:
                 return True
             if self.platform.cloud_ready():
                 # tell service query to use the route list in body
                 event = EventEnvelope()
                 event.set_to(self.SERVICE_QUERY).set_header('type', 'find')
                 event.set_header('route', '*').set_body(routes)
                 result = self.request(event, 8.0)
                 if isinstance(
                         result,
                         EventEnvelope) and result.get_body() is not None:
                     return result.get_body()
     return False
Example #3
0
 def send_payload(self, data: dict):
     payload = msgpack.packb(data, use_bin_type=True)
     payload_len = len(payload)
     if 'type' in data and data[
             'type'] == 'event' and 'event' in data and payload_len > self.max_ws_payload:
         evt = data['event']
         if 'id' in evt:
             msg_id = evt['id']
             total = int(payload_len / self.max_ws_payload)
             if payload_len > total:
                 total += 1
             buffer = io.BytesIO(payload)
             count = 0
             for i in range(total):
                 count += 1
                 block = EventEnvelope()
                 block.set_header('id', msg_id)
                 block.set_header('count', count)
                 block.set_header('total', total)
                 block.set_body(buffer.read(self.max_ws_payload))
                 block_map = dict()
                 block_map['type'] = 'block'
                 block_map['block'] = block.to_map()
                 block_payload = msgpack.packb(block_map, use_bin_type=True)
                 envelope = EventEnvelope()
                 envelope.set_to(self.OUTGOING_WS_PATH).set_header(
                     'type', 'bytes').set_body(block_payload)
                 self.platform.send_event(envelope)
     else:
         envelope = EventEnvelope()
         envelope.set_to(self.OUTGOING_WS_PATH).set_header(
             'type', 'bytes').set_body(payload)
         self.platform.send_event(envelope)
Example #4
0
 def _life_cycle(self, headers: dict, body: any):
     for subscriber in self._subscription:
         try:
             event = EventEnvelope()
             event.set_to(subscriber).set_headers(headers).set_body(body)
             self.platform.send_event(event)
         except ValueError as e:
             self.log.warn(
                 f'Unable to relay life cycle event {headers} to {subscriber} - {e}'
             )
 def logger(self, event: EventEnvelope):
     if isinstance(event, EventEnvelope):
         self.log.info('trace=' + str(event.get_headers()) +
                       ', annotations=' + str(event.get_body()))
         # forward to user provided distributed trace logger if any
         current_time = time.time()
         if self._dt_last_check is None or current_time - self._dt_last_check > 5.0:
             self._dt_last_check = current_time
             self._dt_found = self.platform.exists(self._dt_processor)
         if self._dt_found:
             te = EventEnvelope()
             te.set_to(self._dt_processor).set_body(event.get_body())
             for h in event.get_headers():
                 te.set_header(h, event.get_header(h))
             self.platform.send_event(te)
 def logger(self, event: EventEnvelope):
     if isinstance(event, EventEnvelope):
         self.log.info(
             f'trace={event.get_headers()}, annotations={event.get_body()}')
         if self.platform.is_trace_supported():
             # forward to user provided distributed trace logger if any
             current_time = time.time()
             if self._dt_last_check is None or current_time - self._dt_last_check > 5.0:
                 self._dt_last_check = current_time
                 self._dt_found = self.platform.exists(self._dt_processor)
             if self._dt_found:
                 trace_event = EventEnvelope()
                 trace_event.set_to(self._dt_processor).set_body(
                     {'annotations': event.get_body()})
                 for h in event.get_headers():
                     trace_event.set_header(h, event.get_header(h))
                 self.platform.send_event(trace_event)
Example #7
0
 def _get_server_config(self, headers: dict, body: any):
     if 'type' in headers:
         # at this point, login is successful
         if headers['type'] == 'system.config' and isinstance(body, dict):
             if self.MAX_PAYLOAD in body:
                 self.max_ws_payload = body[self.MAX_PAYLOAD]
                 self.log.info(
                     'Automatic segmentation when event payload exceeds ' +
                     format(self.max_ws_payload, ',d'))
             # advertise public routes to language connector
             for r in self.platform.get_routes('public'):
                 self.send_payload({'type': 'add', 'route': r})
             # tell server that I am ready
             self.send_payload({'type': 'ready'})
         # server acknowledges my ready signal
         if headers['type'] == 'ready':
             self.ready = True
             self.log.info('Ready')
             # redo subscription if any
             if self.platform.has_route('pub.sub.sync'):
                 event = EventEnvelope()
                 event.set_to('pub.sub.sync').set_header(
                     'type', 'subscription_sync')
                 self.platform.send_event(event)
Example #8
0
    async def connection_handler(self, url):
        try:
            async with aiohttp.ClientSession(
                    loop=self._loop,
                    timeout=aiohttp.ClientTimeout(total=10)) as session:
                full_path = url + '/' + self.origin
                self.ws = await session.ws_connect(full_path)
                envelope = EventEnvelope()
                envelope.set_to(self.INCOMING_WS_PATH).set_header(
                    'type', 'open')
                self.platform.send_event(envelope)
                self.log.info("Connected to " + full_path)
                closed = False
                self.last_active = time.time()

                while self.normal:
                    try:
                        msg = await self.ws.receive(timeout=1)
                    except asyncio.TimeoutError:
                        if not self.normal:
                            break
                        else:
                            # idle - send keep-alive
                            now = time.time()
                            if self.is_connected(
                            ) and now - self.last_active > 30:
                                self.last_active = now
                                self.send_keep_alive()
                            continue

                    # receive incoming event
                    self.last_active = time.time()
                    if msg.type == aiohttp.WSMsgType.TEXT:
                        if self.platform.has_route(self.INCOMING_WS_PATH):
                            envelope = EventEnvelope()
                            envelope.set_to(self.INCOMING_WS_PATH).set_header(
                                'type', 'text').set_body(msg.data)
                            self.platform.send_event(envelope)
                        else:
                            break
                    elif msg.type == aiohttp.WSMsgType.BINARY:
                        if self.platform.has_route(self.INCOMING_WS_PATH):
                            envelope = EventEnvelope()
                            envelope.set_to(self.INCOMING_WS_PATH).set_header(
                                'type', 'bytes').set_body(msg.data)
                            self.platform.send_event(envelope)
                        else:
                            break
                    else:
                        if msg.type == aiohttp.WSMsgType.ERROR:
                            self.log.error("Unexpected connection error")
                        if msg.type == aiohttp.WSMsgType.CLOSING:
                            # closing signal received - close the connection now
                            self.log.info("Disconnected, status=" +
                                          str(self.close_code) + ", message=" +
                                          self.close_message)
                            await self.ws.close(code=self.close_code,
                                                message=bytes(
                                                    self.close_message,
                                                    'utf-8'))
                            if self.platform.has_route(self.INCOMING_WS_PATH):
                                envelope = EventEnvelope()
                                envelope.set_to(self.INCOMING_WS_PATH).set_body(self.close_message)\
                                        .set_header('type', 'close').set_header('status', self.close_code)
                                self.platform.send_event(envelope)
                            closed = True
                        if msg.type == aiohttp.WSMsgType.CLOSE or msg.type == aiohttp.WSMsgType.CLOSED:
                            self.close_code = 1001 if msg.data is None else msg.data
                            self.close_message = 'OK' if msg.extra is None else str(
                                msg.extra)
                            self.log.info("Disconnected, status=" +
                                          str(self.close_code) + ", message=" +
                                          self.close_message)
                            if self.platform.has_route(self.INCOMING_WS_PATH):
                                envelope = EventEnvelope()
                                envelope.set_to(self.INCOMING_WS_PATH).set_body(self.close_message)\
                                        .set_header('type', 'close').set_header('status', self.close_code)
                                self.platform.send_event(envelope)
                            closed = True
                        break
                if not closed:
                    await self.ws.close(code=1000, message=b'OK')
                    self.ws = None
                    if self.platform.has_route(self.INCOMING_WS_PATH):
                        envelope = EventEnvelope()
                        envelope.set_to(self.INCOMING_WS_PATH).set_body('OK')\
                            .set_header('type', 'close').set_header('status', 1000)
                        self.platform.send_event(envelope)

        except aiohttp.ClientConnectorError:
            self._skip_url()
            self.log.warn("Unreachable " + url)
Example #9
0
 def _send_life_cycle_event(self, headers: dict):
     event = EventEnvelope()
     event.set_to(self.CONNECTOR_LIFECYCLE).set_headers(headers)
     self.platform.send_event(event)