示例#1
0
async def check_rtsp_availability(rtsp_link, timeout):
    """
    This function needed because some rtsp links requires
    to authenticate and pyav lib may freeze in such cases.
    If some rtsp link require authentication contact NVR admins to replace it with working link.
    """
    url = urlparse(rtsp_link)
    ip = url.hostname
    port = url.port if url.port else 554
    reader = None
    writer = None

    try:
        reader, writer = await asyncio.wait_for(asyncio.open_connection(
            ip, port),
                                                timeout=timeout)
        is_available = bool(reader) and bool(writer)
    except asyncio.TimeoutError:
        raise web.HTTPBadGateway(
            text='Can not establish connection with rtsp media source')
    except OSError:
        raise web.HTTPBadGateway(
            text='Can not establish connection with rtsp media source')
    finally:
        if writer:
            writer.close()
            await writer.wait_closed()

    if not is_available:
        raise web.HTTPBadGateway(
            text='Can not establish connection with rtsp media source')
示例#2
0
 async def handle(self, request: web.Request, camera: Camera) -> web.StreamResponse:
     """Serve camera stream, possibly with interval."""
     if (interval_str := request.query.get("interval")) is None:
         stream = await camera.handle_async_mjpeg_stream(request)
         if stream is None:
             raise web.HTTPBadGateway()
         return stream
async def receive_and_echo(request):
    """Accept and validate an SMS delivery."""

    secret = request.app["secret"]

    if request.content_type == "application/json":
        payload = await request.json()
    else:
        payload = await request.post()

    msg = SMSMessage.from_payload(payload)
    logging.info("Received message: %s", msg)

    sig = request.headers.get("X-Telnyx-Signature")
    raw_payload = await request.read()
    epoch = get_epoch_from_header(sig)
    expected_sig = webhook_sig_hs256(secret, raw_payload, epoch)
    if sig != expected_sig:
        logging.error("Invalid signature: %s (expected %s)", sig, expected_sig)
        return web.HTTPBadRequest(text="Invalid signature")

    try:
        echo_msg = msg.echo_message()
        await async_send(echo_msg, secret)
    except SMSSendError as e:
        logging.error("Echo failed: %s", e)
        return web.HTTPBadGateway(text="Echo failed")

    logging.info("Echoed message: %s", echo_msg)
    return web.Response(text="Echo OK")
示例#4
0
async def receive_and_echo(request):
    """Accept and validate an SMS delivery."""

    secret = request.app["secret"]

    if request.content_type == "application/json":
        payload = await request.json()
    else:
        payload = await request.post()

    msg = SMSMessage.from_payload(payload)
    logging.info("Received message: %s", msg)

    sig = request.headers.get(SIGNATURE_HEADER_KEY)
    raw_payload = await request.read()
    timestamp, _ = parse_signature(sig)
    expected_sig = generate_signature(secret=secret,
                                      payload=raw_payload,
                                      timestamp=timestamp)
    if sig != expected_sig:
        logging.error("Invalid signature: %s (expected %s)", sig, expected_sig)
        return web.HTTPBadRequest(text="Invalid signature")

    try:
        echo_msg = msg.echo_message()
        await async_send(echo_msg, secret)
    except SMSSendError as e:
        logging.error("Echo failed: %s", e)
        return web.HTTPBadGateway(text="Echo failed")

    logging.info("Echoed message: %s", echo_msg)
    return web.Response(text="Echo OK")
示例#5
0
async def _put_file_to_object_store(uuid: str, content_type: str, data,
                                    filename: T.Optional[str]=None):
    _logger.debug("url: %s\n", _BASE_URL + uuid)
    _logger.debug("Authorization: %s", _AUTHORIZATION)
    headers = {
        'Authorization': _AUTHORIZATION,
        'Content-Type': content_type
    }
    if filename is not None:
        headers['Content-Disposition'] = helpers.content_disposition_header(
            'attachment', filename=filename
        )
    async with aiohttp.ClientSession() as session:
        async with session.put(
            _BASE_URL + uuid,
            data=data,
            headers=headers,
            chunked=True,
            expect100=True
        ) as response:
            if response.status >= 400:
                _logger.error(
                    "Couldn't store file in object store.\n"
                    "%s %s:\n%s\n%r", response.status, response.reason,
                    await response.text(), response
                )
                raise web.HTTPBadGateway()
示例#6
0
 async def handle_request(client_request):
     headers = filter_headers(client_request, OMIT_REQ_HEADERS)
     headers["Host"] = hostname
     request = {
         "method": client_request.method,
         "url": "{}{}".format(remote_address, client_request.rel_url),
         "headers": headers,
         "allow_redirects": False,
         "data": await client_request.read(),
     }
     async with ClientSession() as session:
         try:
             async with session.request(**request) as response:
                 logger.debug(
                     "%s : %s -> %d, %s",
                     request["method"],
                     request["url"],
                     response.status,
                     response.content_type,
                 )
                 return await build_response(response)
         except ClientConnectionError as exc:
             msg = "{} : {} -> {}".format(
                 request["method"], request["url"], str(exc)
             )
             logger.error(msg)
             return web.HTTPBadGateway(reason=msg)
示例#7
0
async def handle_rpc(request):
    body = await request.json()
    if ('method' not in body or not isinstance(body['method'], str)):
        logger.warn('bad request for for body %s', body)
        return web.HTTPBadRequest()

    m = parse_method(body['method'])
    if not m:
        logger.warn('parse method error %s', body)
        return web.HTTPBadRequest()

    if _whitelist is not None:
        if body['method'] not in _whitelist:
            logger.warn('method not in whitelist')
            return web.HTTPForbidden()

    # TODO: srv::method white list
    srv, method = m.group('srv'), m.group('method')

    params = body['params']
    try:
        timeout = float(request.headers.get('X-Bbox-Proxy-Timeout', '8'))
    except ValueError:
        timeout = 8

    try:
        r = await pool.request(srv,
                               method,
                               *params,
                               req_id=body.get('id'),
                               timeout=timeout)
    except asyncio.TimeoutError:
        logging.warn('timeout error on request srv %s, method %s',
                     srv,
                     method,
                     exc_info=True)
        return web.HTTPBadGateway()
    except ConnectionError:
        logger.warn('connect error on request srv %s, method %s',
                    srv,
                    method,
                    exc_info=True)
        return web.HTTPBadGateway()
    return web.json_response(r)
示例#8
0
 async def handle(self, request: web.Request, camera: Camera) -> web.StreamResponse:
     """Serve camera stream, possibly with interval."""
     if (interval_str := request.query.get("interval")) is None:
         try:
             stream = await camera.handle_async_mjpeg_stream(request)
         except ConnectionResetError:
             stream = None
             _LOGGER.debug("Error while writing MJPEG stream to transport")
         if stream is None:
             raise web.HTTPBadGateway()
         return stream
示例#9
0
 async def __call__(self, request):
     kw = None
     if self._has_var_kw_arg or self._has_named_kw_args or self._required_kw_args:
         if request.method == 'POST':
             if not request.content_type:
                 return web.HTTPBadRequest(body='Missing content-type')
             ct = request.content_type.lower()
             if ct.startswith('application/json'):
                 params = await request.json()
                 if not isinstance(params, dict):
                     return web.HTTPBadRequest(body='JSON body must be object.')
                 kw = params
             elif ct.startswith('application/x-www-form-urlencoded') or ct.startswith('multipart/form-data'):
                 params = await request.post()
                 kw = dict(**params) 
             else:
                 return web.HTTPBadGateway(body=('Unsupported content-type: %s' % request.content_type))
         
         if request.method == 'GET':
             qs = request.query_string
             if qs:
                 kw = dict()
                 for k, v in parse.parse_qs(qs, True).items():
                     kw[k] = v
     if kw is None:
         kw = dict(**request.match_info)
     else:
         if not self._has_var_kw_arg and self._named_kw_args:
             # remove all unamed kw:
             copy = dict()
             for name in self._named_kw_args:
                 if name in kw:
                     copy[name] = kw[name]
             kw = copy
         # check named arg:
         for k, v in request.match_info.items():
             if k in kw:
                 logging.warning('Duplicate arg name in named arg and kw args: %s' , k)
             kw[k] = v
     if self._has_request_arg:
         kw['request'] = request
     # check required kw:
     if self._required_kw_args:
         for name in self._required_kw_args:
             if not name in kw:
                 return web.HTTPBadRequest(body=('Missing argument: %s' % name))
     logging.info('call with args: %s', str(kw))
     try:
         r = await self._func(**kw)
         return r
     except APIError as e:
         return dict(error=e.error, data=e.data, message=e.message)
示例#10
0
async def offer(request):
    request_url = request.match_info['stream']
    streams = await get_streams(args.nvr_token)

    if request_url not in streams:
        raise web.HTTPNotFound(text='No rtsp source related to this url')

    play_from = streams[request_url]
    if not play_from:
        raise web.HTTPBadGateway(
            text=
            'NVR response with cam rtsp link is empty. Contact NVR admins to fix it'
        )

    url = urlparse(play_from)
    if url.scheme == 'rtsp':
        await check_rtsp_availability(play_from, timeout=10)

    params = await request.json()
    offer = RTCSessionDescription(sdp=params["sdp"], type=params["type"])

    pc = RTCPeerConnection()
    pcs.add(pc)

    @pc.on("iceconnectionstatechange")
    async def on_iceconnectionstatechange():
        print("ICE connection state is %s" % pc.iceConnectionState)
        if pc.iceConnectionState == "failed":
            await pc.close()
            pcs.discard(pc)

    player = MediaPlayer(play_from)

    await pc.setRemoteDescription(offer)
    for t in pc.getTransceivers():
        if t.kind == "audio" and player.audio:
            pc.addTrack(player.audio)
        elif t.kind == "video" and player.video:
            track = VideoTransformTrack(player.video, request_url)
            pc.addTrack(track)

    answer = await pc.createAnswer()
    await pc.setLocalDescription(answer)

    return web.Response(content_type="application/json",
                        headers=cors_headers,
                        text=json.dumps({
                            "sdp": pc.localDescription.sdp,
                            "type": pc.localDescription.type
                        }))
示例#11
0
async def get_link(request):
    request_url = request.match_info['stream']
    streams = await get_streams(args.nvr_token)

    if request_url not in streams:
        raise web.HTTPNotFound(text='No rtsp source related to this url')

    play_from = streams[request_url]
    if not play_from:
        raise web.HTTPBadGateway(
            text=
            'NVR response with cam rtsp link is empty. Contact NVR admins to fix it'
        )

    # play_from = 'rtsp://*****:*****@' + play_from.lstrip('rtsp://')
    return web.Response(headers=cors_headers, text=play_from)
示例#12
0
async def proxy(request: web.Request) -> web.Response:
    if not config.get_permissions(request["token"].user_id).admin:
        raise Error.no_access_docker
    path = request.match_info["path"]
    query = request.query.copy()
    headers = request.headers.copy()
    del headers["Host"]
    del headers["Authorization"]

    try:
        timeout = aiohttp.ClientTimeout(total=None, connect=5, sock_connect=5, sock_read=None)
        resp = await http.request(request.method, host / path, headers=headers,
                                  params=query, data=request.content, timeout=timeout)
    except aiohttp.ClientError:
        raise web.HTTPBadGateway(text="Failed to contact Docker daemon")
    return web.Response(status=resp.status, headers=resp.headers, body=resp.content)
async def client_handler(r : web.Request):
    """Handler for websocket connections and messages"""
    if not NODES:
        return web.HTTPBadGateway()

    ip = UTIL.get_request_ip(r)
    if (sessions_count(ip) >= 2):
        return web.HTTPForbidden()

    ws = web.WebSocketResponse(heartbeat=30)
    try:
        await ws.prepare(r)
        # Connection Opened
    except:
        log.server_logger.error('Failed to prepare websocket: %s', UTIL.get_request_ip(r))
        return ws
    ws.id = str(uuid.uuid4())

    global CLIENTS
    CLIENTS[ws.id] = {'ws':ws, 'events':set(), 'ip':ip}

    try:
        log.server_logger.info('new client connection;%s;%s;User-Agent:%s', ip, ws.id, str(
            r.headers.get('User-Agent')))
        
        async for msg in ws:
            if msg.type == WSMsgType.TEXT:
                if msg.data == 'close':
                    await ws.close()
                else:
                    res = await handle_client_messages(r, msg.data, ws=ws)
                    if res:
                        res = json.dumps(res)
                        log.server_logger.debug('Sending response %s to %s', res, ip)
                        await ws.send_str(res)
            elif msg.type == WSMsgType.CLOSE:
                log.server_logger.info('Client Connection closed normally')
                break
            elif msg.type == WSMsgType.ERROR:
                log.server_logger.info('Client Connection closed with error %s', ws.exception())
                break
        log.server_logger.info('Client connection closed normally')
    except Exception:
        log.server_logger.exception('Client Closed with exception')
    finally:
        del CLIENTS[ws.id]
    return ws
示例#14
0
文件: gateway.py 项目: Freeza91/bbox
async def handle_req(request):
    if not default_backend:
        return web.HTTPNotFound()
    webreq = {
        'method': request.method,
        'path': request.path,
        'qs': request.query_string,
        'headers': dict(request.headers.items()),
        'body': None
    }

    if request.method in ('POST', 'PUT'):
        ctype = request.headers.get('Content-Type', 'application/octet-stream')
        if ctype in ('application/x-www-form-urlencoded', 'application/json'):
            # ONLY parse known body
            body = await request.post()
            webreq['body'] = dict(body.items())

    srv, method = default_backend.split('::')
    try:
        r = await srv_pool.request(srv, method, webreq)
    except ConnectionError:
        return web.HTTPBadGateway()
    except NoServiceFound as e:
        return web.HTTPNotFound(str(e))

    if r['result']:
        res = r['result']
        if isinstance(res, str):
            return web.Response(body=res)
        elif 'body' in res:
            headers = res.get('headers', {})
            body = res['body']
            if isinstance(body, str):
                return web.Response(body=body, headers=headers)
            else:
                headers.pop('Content-Type', None)
                return web.json_response(body, headers=headers)
        else:
            return web.json_response(res)
    else:
        code = r['error'].get('code', '500')
        if code.isdigit():
            code = int(code)
        else:
            code = 500
        return web.Response(status=code, body=r['error'].get('message', ''))
示例#15
0
    async def authenticate(self, request):
        token = self.get_token(request)
        if token is None:
            raise unauthorized("jupyterhub")

        url = "{}/authorizations/token/{}".format(
            self.jupyterhub_api_url,
            quote(token, safe=""),
        )

        kwargs = {
            "headers": {
                "Authorization": "token %s" % self.jupyterhub_api_token
            },
            "ssl": self.ssl_context,
        }

        resp = await self.session.get(url, **kwargs)

        if resp.status < 400:
            data = await resp.json()
            # "groups" attribute doesn't exists in case of a service
            return User(
                data["name"],
                groups=data.get("groups", []),
                admin=data.get("admin", False),
            )
        elif resp.status == 404:
            self.log.debug("Token for non-existent user requested")
            raise unauthorized("jupyterhub")
        else:
            if resp.status == 403:
                err = web.HTTPInternalServerError(
                    reason=
                    "Permission failure verifying user's JupyterHub API token")
            elif resp.status >= 500:
                err = web.HTTPBadGateway(
                    reason=
                    "Upstream failure verifying user's JupyterHub API token")
            else:
                err = web.HTTPInternalServerError(
                    reason="Failure verifying user's JupyterHub API token")

            self.log.error("%s - code: %s, reason: %s", err.reason,
                           resp.status, resp.reason)
            raise err
示例#16
0
    async def handle(self, request: web.Request, camera: Camera) -> web.StreamResponse:
        """Serve camera stream, possibly with interval."""
        interval_str = request.query.get("interval")
        if interval_str is None:
            stream = await camera.handle_async_mjpeg_stream(request)
            if stream is None:
                raise web.HTTPBadGateway()
            return stream

        try:
            # Compose camera stream from stills
            interval = float(interval_str)
            if interval < MIN_STREAM_INTERVAL:
                raise ValueError(f"Stream interval must be be > {MIN_STREAM_INTERVAL}")
            return await camera.handle_async_still_stream(request, interval)
        except ValueError as err:
            raise web.HTTPBadRequest() from err
示例#17
0
    async def get_articles(self, request):
        request_params = request.query
        query_str = request_params.get('query_str')
        if not query_str:
            raise web.HTTPBadGateway()

        current_ts = time.time()
        key = f'{query_str}-{current_ts}'
        await self.kafka_producer.send('request_topic',
                                       value=bytes(query_str, 'utf-8'),
                                       key=bytes(key, 'utf-8'))
        logging.info(f'{query_str} was sent to kafka')
        event = asyncio.Event()
        self.synchronization_events[key] = event
        await event.wait()
        articles = self.articles_storage.pop(key)
        return web.json_response(articles)
示例#18
0
async def client_handler(r: web.Request):
    """Handler for websocket connections and messages"""
    if not r.app['nodes']:
        return web.HTTPBadGateway()

    ws = web.WebSocketResponse(heartbeat=30)
    try:
        await ws.prepare(r)
        # Connection Opened
    except:
        log.server_logger.error('Failed to prepare websocket: %s',
                                UTIL.get_request_ip(r))
        return ws
    ws.id = str(uuid.uuid4())
    ip = UTIL.get_request_ip(r)
    r.app['clients'][ws.id] = {'ws': ws, 'accounts': set()}
    log.server_logger.info('new client connection;%s;%s;User-Agent:%s', ip,
                           ws.id, str(r.headers.get('User-Agent')))

    try:
        async for msg in ws:
            if msg.type == WSMsgType.TEXT:
                if msg.data == 'close':
                    await ws.close()
                else:
                    reply = await handle_client_messages(r, msg.data, ws=ws)
                    if reply:
                        log.server_logger.debug('Sending response %s to %s',
                                                reply, ip)
                        await ws.send_str(reply)
            elif msg.type == WSMsgType.CLOSE:
                log.server_logger.info('Client Connection closed normally')
                break
            elif msg.type == WSMsgType.ERROR:
                log.server_logger.info(
                    'Client Connection closed with error %s', ws.exception())
                break
        log.server_logger.info('Client connection closed normally')
    except Exception:
        log.server_logger.exception('Client Closed with exception')
    finally:
        await destory_client(r, ws.id)
    return ws
示例#19
0
async def handle_rpc(request: web.Request) -> web.Response:  # type: ignore
    body = await request.json()

    try:
        req = Request(body)
    except DataError as e:
        logger.warn('json parse error %s', body)
        return web.HTTPBadRequest('json parse error')

    if _whitelist is not None:
        if not req.allowed(_whitelist):
            logger.warn('method not allowed')
            return web.HTTPForbidden()

    try:
        timeout = float(request.headers.get('X-Bbox-Proxy-Timeout', '20'))
    except ValueError:
        timeout = 20

    try:
        r = await srv_pool.request_obj(req, timeout=timeout)
        return web.json_response(r)
    except asyncio.TimeoutError:
        logging.warn('timeout error on request %s',
                     req.full_method,
                     exc_info=True)
    except ClientConnectorError:
        logger.warn('client connector error, method %s',
                    req.method,
                    exc_info=True)
        await get_cluster().get_boxes()
    except ConnectionError:
        logger.warn('connect error on request %s',
                    req.full_method,
                    exc_info=True)
        await get_cluster().get_boxes()
    except NoServiceFound:
        logger.warn('no service found for %s', req.full_method)
        await get_cluster().get_boxes()
        return web.HTTPNotFound()

    return web.HTTPBadGateway()
示例#20
0
async def discover(host: str, port: int, path: str, verb: str,
                   endpoint: str) -> dict[str, Any]:
    """Call discovery service and get microservice connection data.

    :param host: Discovery host name.
    :param port: Discovery port.
    :param path: Discovery path.
    :param verb: Endpoint Verb.
    :param endpoint: Endpoint url.
    :return: The response of the discovery.
    """

    url = URL.build(scheme="http",
                    host=host,
                    port=port,
                    path=path,
                    query={
                        "verb": verb,
                        "path": endpoint
                    })
    try:
        async with ClientSession() as session:
            async with session.get(url=url) as response:
                if not response.ok:
                    if response.status == 404:
                        raise web.HTTPNotFound(
                            text=
                            f"The {endpoint!r} path is not available for {verb!r} method."
                        )
                    raise web.HTTPBadGateway(
                        text="The Discovery Service response is wrong.")

                data = await response.json()
    except ClientConnectorError:
        raise web.HTTPGatewayTimeout(
            text="The Discovery Service is not available.")

    data["port"] = int(data["port"])

    return data
示例#21
0
async def proxy(url: URL, secret: str, request: web.Request,
                path_prefix: str) -> web.Response:
    if not secret:
        raise Error.bridge_disabled
    query = request.query.copy()
    query["user_id"] = request["token"].user_id
    headers = request.headers.copy()
    headers["Authorization"] = f"Bearer {secret}"

    if path_prefix:
        url /= path_prefix

    path = request.match_info.get("path", None)
    if path:
        url /= path

    try:
        resp = await http.request(request.method,
                                  url,
                                  headers=headers,
                                  params=query,
                                  data=request.content)
    except aiohttp.ClientError:
        log.debug("Failed to proxy request", exc_info=True)
        raise web.HTTPBadGateway(text="Failed to contact bridge")
    except CancelledError:
        log.debug(
            f"Proxying request to {url} was cancelled before it responded")
        raise
    except Exception:
        log.warning(f"Proxying request to {url} threw unhandled exception",
                    exc_info=True)
        raise

    return web.Response(status=resp.status,
                        headers=resp.headers,
                        body=resp.content)
示例#22
0
async def dev_deploy_branch(request, userdata):
    app = request.app
    try:
        params = await request.json()
    except Exception:
        message = 'could not read body as JSON'
        log.info('dev deploy failed: ' + message, exc_info=True)
        raise web.HTTPBadRequest(text=message)

    try:
        branch = FQBranch.from_short_str(params['branch'])
        steps = params['steps']
    except Exception:
        message = f'parameters are wrong; check the branch and steps syntax.\n\n{params}'
        log.info('dev deploy failed: ' + message, exc_info=True)
        raise web.HTTPBadRequest(text=message)

    gh = app['github_client']
    request_string = f'/repos/{branch.repo.owner}/{branch.repo.name}/git/refs/heads/{branch.name}'

    try:
        branch_gh_json = await gh.getitem(request_string)
        sha = branch_gh_json['object']['sha']
    except Exception:
        message = f'error finding {branch} at GitHub'
        log.info('dev deploy failed: ' + message, exc_info=True)
        raise web.HTTPBadRequest(text=message)

    unwatched_branch = UnwatchedBranch(branch, sha, userdata)

    batch_client = app['batch_client']

    try:
        batch_id = await unwatched_branch.deploy(batch_client, steps)
    except Exception as e:  # pylint: disable=broad-except
        raise web.HTTPBadGateway(text=f'starting the deploy failed due to {e}')
    return web.json_response({'sha': sha, 'batch_id': batch_id})
示例#23
0
    async def _identify_to_kisee(self, data: LoginCredentials):
        """Async request to identify to kisee"""
        create_token_endpoint = await self.get_endpoint("jwt")
        async with aiohttp.ClientSession() as session:
            async with session.post(
                create_token_endpoint,
                headers={
                    "Content-Type": "application/json",
                    "Accept": "application/vnd.coreapi+json",
                },
                json=data,
            ) as response:

                if response.status == 403:
                    raise web.HTTPForbidden(reason="Can not authenticate on kisee")
                if response.status != 201:
                    raise web.HTTPBadGateway(
                        reason="Something went wrong with identity provider"
                    )

                kisee_response = await response.text()
                kisee_response = json.loads(kisee_response)

        return kisee_response
示例#24
0
async def submit_job(request):
    """
    Function to submit a query.
    :param request: used to get the params to connect to the db
    :return: json with job_id

    Example:
    curl -H "Content-Type:application/json" -d "{\"databases\": [\"miRBase\"], \"query\": \"CUAUACAAUCUACUGUCUUUC\"}" localhost:8002/api/submit-job

    ---
    tags:
    - Jobs
    summary: Accepts a job for execution
    consumes:
     - application/json
    parameters:
     - in: body
       name: Sequence and database
       description: Query sequence and database to be used in the search
       required: true
       schema:
         properties:
           query:
             type: string
             description: Query sequence
             example: "CUAUACAAUCUACUGUCUUUC"
           databases:
             type: array
             description: Database to search the query sequence against. Empty list uses the RNAcentral database
             example: ['mirbase']
         required:
           - query
           - databases
    responses:
      201:
        description: Created
      400:
        description: Bad request (either query is not a nucleotide sequence, or the database is not in RNAcentral)
      500:
        description: Internal server error
    """
    data = await request.json()

    # converts all uppercase characters to lowercase.
    if data['databases']:
        data['databases'] = [db.lower() for db in data['databases']]

    try:
        data = serialize(request, data)
    except (KeyError, TypeError, ValueError) as e:
        raise web.HTTPBadRequest(text=str(e)) from e

    # database that the user wants to use to perform the search
    databases = producer_to_consumers_databases(data['databases'])

    # check if this query has already been searched
    job_list = await sequence_exists(request.app['engine'], data['query'])

    job_id = None
    if job_list:
        # check the database used in each job_id.
        # set job_id if the database used is the same as in "databases"
        for job in job_list:
            if await database_used_in_search(request.app['engine'], job,
                                             databases):
                job_id = job
                break

    # do the search if the data is not in the database
    if not job_id:
        # check for unfinished jobs
        unfinished_job = await find_highest_priority_jobs(request.app['engine']
                                                          )

        # get URL - for statistical purposes
        try:
            url = data['url']
        except KeyError:
            url = ''

        # get priority
        try:
            priority = data['priority']
        except KeyError:
            priority = 'low'

        expert_dbs = [
            "rnacentral.org", "rfam.xfam.org", "rfam.org", "mirbase.org",
            "scottgroup.med.usherbrooke.ca", "gtrnadb.ucsc.edu"
        ]
        search_from_expert_db = [item for item in expert_dbs if item in url]
        if not search_from_expert_db:
            priority = 'low'

        # save metadata about this job to the database
        job_id = await save_job(request.app['engine'], data['query'],
                                data['description'], url, priority)

        # save metadata about job_chunks to the database
        # TODO: what if Job was saved and JobChunk was not? Need transactions?
        for database in databases:
            # save job_chunk with "created" status. This prevents the check_chunks_and_consumers function,
            # which runs every 5 seconds, from executing the same job_chunk again.
            await save_job_chunk(request.app['engine'], job_id, database)

        # save metadata about infernal_job to the database
        # TODO: what if Job was saved and InfernalJob was not? Need transactions?
        await save_infernal_job(request.app['engine'], job_id, priority)

        # if there are unfinished jobs, change the status of each new job_chunk to pending;
        # otherwise try starting the job
        if unfinished_job:
            for database in databases:
                try:
                    await set_job_chunk_status(
                        request.app['engine'],
                        job_id,
                        database,
                        status=JOB_CHUNK_STATUS_CHOICES.pending)
                except Exception as e:
                    return web.HTTPBadGateway(text=str(e))
        else:
            # check for available consumers
            consumers = await find_available_consumers(request.app['engine'])

            # if consumers are available, delegate to infernal_job first
            if consumers:
                consumer = consumers.pop(0)

                try:
                    await delegate_infernal_job_to_consumer(
                        engine=request.app['engine'],
                        consumer_ip=consumer.ip,
                        consumer_port=consumer.port,
                        job_id=job_id,
                        query=data['query'])
                except Exception as e:
                    return web.HTTPBadGateway(text=str(e))

            # after infernal_job, delegate consumers to job_chunks
            for index in range(min(len(consumers), len(databases))):
                try:
                    await delegate_job_chunk_to_consumer(
                        engine=request.app['engine'],
                        consumer_ip=consumers[index].ip,
                        consumer_port=consumers[index].port,
                        job_id=job_id,
                        database=databases[index],
                        query=data['query'])
                except Exception as e:
                    return web.HTTPBadGateway(text=str(e))

            # if no consumer is available, change the status of the remaining job_chunks to pending
            for index in range(len(consumers), len(databases)):
                try:
                    await set_job_chunk_status(
                        request.app['engine'],
                        job_id,
                        databases[index],
                        status=JOB_CHUNK_STATUS_CHOICES.pending)
                except Exception as e:
                    return web.HTTPBadGateway(text=str(e))

    return web.json_response({"job_id": job_id}, status=201)
示例#25
0
 async def handler(request: web.Request) -> web.Response:
     raise web.HTTPBadGateway()