Exemplo n.º 1
0
async def get_query(query_id):
    request.socket.send_json({"action": "get_sql", "query_id": query_id})
    message = await request.socket.recv_json()
    current_app.logger.debug(f"Got message: {message}")
    if message["status"] == "done":
        results_streamer = stream_with_context(generate_json)(message["sql"],
                                                              query_id)
        mimetype = "application/json"

        current_app.logger.debug("Returning.")
        return (
            results_streamer,
            200,
            {
                "Transfer-Encoding": "chunked",
                "Content-Disposition": f"attachment;filename={query_id}.json",
                "Content-type": mimetype,
            },
        )
    elif message["status"] == "running":
        return jsonify({}), 202
    elif message["status"] == "error":
        return jsonify({"status": "Error", "msg": message["error"]}), 403
    else:
        return jsonify({}), 404
Exemplo n.º 2
0
async def get_query_result(query_id):
    await current_user.can_get_results_by_query_id(query_id=query_id)
    msg = {
        "request_id": request.request_id,
        "action": "get_sql_for_query_result",
        "params": {
            "query_id": query_id
        },
    }
    request.socket.send_json(msg)
    reply = await request.socket.recv_json()
    current_app.flowapi_logger.debug(f"Received reply: {reply}",
                                     request_id=request.request_id)

    if reply["status"] == "error":
        # TODO: check that this path is fully tested!
        query_state = reply["payload"]["query_state"]
        if query_state in ("executing", "queued"):
            return jsonify({}), 202
        elif query_state == "errored":
            return (
                jsonify({
                    "status": "Error",
                    "msg": reply["msg"]
                }),
                403,
            )  # TODO: should this really be 403?
        elif query_state in ("awol", "known"):
            return (jsonify({"status": "Error", "msg": reply["msg"]}), 404)
        else:
            return (
                jsonify({
                    "status": "Error",
                    "msg": f"Unexpected query state: {query_state}"
                }),
                500,
            )
    else:
        sql = reply["payload"]["sql"]
        results_streamer = stream_with_context(stream_result_as_json)(
            sql, additional_elements={
                "query_id": query_id
            })
        mimetype = "application/json"

        current_app.flowapi_logger.debug(
            f"Returning result of query {query_id}.",
            request_id=request.request_id)
        return (
            results_streamer,
            200,
            {
                "Transfer-Encoding": "chunked",
                "Content-Disposition": f"attachment;filename={query_id}.json",
                "Content-type": mimetype,
            },
        )
Exemplo n.º 3
0
async def get_geography(aggregation_unit):
    current_user.can_get_geography(aggregation_unit=aggregation_unit)
    msg = {
        "request_id": request.request_id,
        "action": "get_geography",
        "params": {
            "aggregation_unit": aggregation_unit
        },
    }
    request.socket.send_json(msg)
    #  Get the reply.
    reply = await request.socket.recv_json()
    current_app.flowapi_logger.debug(f"Got message: {reply}",
                                     request_id=request.request_id)

    if reply["status"] == "error":
        return jsonify({
            "status": "Error",
            "msg": "Internal server error"
        }), 500

    try:
        query_state = reply["payload"]["query_state"]
        if query_state == "completed":
            results_streamer = stream_with_context(stream_result_as_json)(
                reply["payload"]["sql"],
                result_name="features",
                additional_elements={
                    "type": "FeatureCollection"
                },
            )
            mimetype = "application/geo+json"

            current_app.flowapi_logger.debug(
                f"Returning {aggregation_unit} geography data.",
                request_id=request.request_id,
            )
            return (
                results_streamer,
                200,
                {
                    "Transfer-Encoding": "chunked",
                    "Content-Disposition":
                    f"attachment;filename={aggregation_unit}.geojson",
                    "Content-type": mimetype,
                },
            )
        # TODO: Reinstate correct status codes for geographies
        #
        # elif query_state == "error":
        #     return jsonify({"status": "Error", "msg": reply["msg"]}), 403
        # elif query_state == "awol":
        #     return (jsonify({"status": "Error", "msg": reply["msg"]}), 404)
    except KeyError:
        # TODO: This should never happen!
        return (jsonify({"status": "Error", "msg": f"No query state."}), 500)
Exemplo n.º 4
0
async def get_query(query_id):
    request.socket.send_json({
        "request_id": request.request_id,
        "action": "get_sql",
        "query_id": query_id
    })
    message = await request.socket.recv_json()
    current_app.logger.debug(f"Got message: {message}")
    try:
        status = message["status"]
    except KeyError:
        return (
            jsonify({
                "status": "Error",
                "msg": "Server responded without status"
            }),
            500,
        )
    if message["status"] == "done":
        results_streamer = stream_with_context(stream_result_as_json)(
            message["sql"], additional_elements={
                "query_id": query_id
            })
        mimetype = "application/json"

        current_app.logger.debug(f"Returning result of query {query_id}.")
        return (
            results_streamer,
            200,
            {
                "Transfer-Encoding": "chunked",
                "Content-Disposition": f"attachment;filename={query_id}.json",
                "Content-type": mimetype,
            },
        )
    elif message["status"] == "running":
        return jsonify({}), 202
    elif message["status"] == "error":
        return jsonify({"status": "Error", "msg": message["error"]}), 403
    elif status == "awol":
        return (jsonify({"status": "Error", "msg": message["error"]}), 404)
    else:
        return jsonify({
            "status": "Error",
            "msg": f"Unexpected status: {status}"
        }), 500
Exemplo n.º 5
0
async def get_geography(aggregation_unit):
    request.socket.send_json(
        {
            "request_id": request.request_id,
            "action": "get_geography",
            "params": {"aggregation_unit": aggregation_unit},
        }
    )
    #  Get the reply.
    message = await request.socket.recv_json()
    current_app.logger.debug(f"Got message: {message}")
    try:
        status = message["status"]
    except KeyError:
        return (
            jsonify({"status": "Error", "msg": "Server responded without status"}),
            500,
        )
    if status == "done":
        results_streamer = stream_with_context(stream_result_as_json)(
            message["sql"],
            result_name="features",
            additional_elements={"type": "FeatureCollection"},
        )
        mimetype = "application/geo+json"

        current_app.logger.debug(f"Returning {aggregation_unit} geography data.")
        return (
            results_streamer,
            200,
            {
                "Transfer-Encoding": "chunked",
                "Content-Disposition": f"attachment;filename={aggregation_unit}.geojson",
                "Content-type": mimetype,
            },
        )
    elif status == "error":
        return jsonify({"status": "Error", "msg": message["error"]}), 403
    elif status == "awol":
        return (jsonify({"status": "Error", "msg": message["error"]}), 404)
    else:
        return (
            jsonify({"status": "Error", "msg": f"Unexpected status: {status}"}),
            500,
        )
Exemplo n.º 6
0
async def get_geography(aggregation_unit):
    """
    Get geojson
    ---
    get:
      parameters:
        - in: path
          name: aggregation_unit
          required: true
          schema:
            type: string
      responses:
        '200':
          content:
            application/geo+json:
              schema:
                type: object
          description: Downloading.
        '401':
          description: Unauthorized.
        '403':
          content:
            application/json:
              schema:
                type: object
          description: Token does not grant run access to this spatial aggregation unit.
        '500':
          description: Server error.
      summary: Get geojson for an aggregation unit
    """
    current_user.can_get_geography(aggregation_unit=aggregation_unit)
    msg = {
        "request_id": request.request_id,
        "action": "get_geography",
        "params": {
            "aggregation_unit": aggregation_unit
        },
    }
    request.socket.send_json(msg)
    #  Get the reply.
    reply = await request.socket.recv_json()
    current_app.flowapi_logger.debug(f"Got message: {reply}",
                                     request_id=request.request_id)

    if reply["status"] == "error":
        try:
            msg = reply["msg"]
        except KeyError:
            msg = "Internal server error"
        return {"status": "Error", "msg": msg}, 500

    try:
        query_state = reply["payload"]["query_state"]
        if query_state == "completed":
            results_streamer = stream_with_context(stream_result_as_json)(
                reply["payload"]["sql"],
                result_name="features",
                additional_elements={
                    "type": "FeatureCollection"
                },
            )
            mimetype = "application/geo+json"

            current_app.flowapi_logger.debug(
                f"Returning {aggregation_unit} geography data.",
                request_id=request.request_id,
            )
            return (
                results_streamer,
                200,
                {
                    "Transfer-Encoding": "chunked",
                    "Content-Disposition":
                    f"attachment;filename={aggregation_unit}.geojson",
                    "Content-type": mimetype,
                },
            )
        # TODO: Reinstate correct status codes for geographies
        #
        # elif query_state == "error":
        #     return {"status": "Error", "msg": reply["msg"]}, 403
        # elif query_state == "awol":
        #     return ({"status": "Error", "msg": reply["msg"]}, 404)
    except KeyError:
        # TODO: This should never happen!
        return ({"status": "Error", "msg": f"No query state."}, 500)
Exemplo n.º 7
0
async def get_query_result(query_id, filetype="json"):
    """
    Get the output of a completed query.
    ---
    get:
      parameters:
        - in: path
          name: query_id
          required: true
          schema:
            type: string
        - in: path
          name: filetype
          required: false
          default: json
          schema:
            type: string
            enum:
              - json
              - geojson
              - csv
      responses:
        '200':
          content:
            application/json:
              schema:
                type: object
            application/geo+json:
              schema:
                type: object
            text/csv:
              schema:
                type: string
          description: Results returning.
        '202':
          content:
            application/json:
              schema:
                type: object
          description: Request accepted.
        '401':
          description: Unauthorized.
        '403':
          content:
            application/json:
              schema:
                type: object
          description: Token does not grant results access to this query or spatial aggregation unit.
        '404':
          description: Unknown ID
        '500':
          description: Server error.
      summary: Get the output of query
    """
    await current_user.can_get_results_by_query_id(query_id=query_id)
    msg = {
        "request_id": request.request_id,
        "action": "get_geo_sql_for_query_result"
        if filetype == "geojson" else "get_sql_for_query_result",
        "params": {
            "query_id": query_id
        },
    }
    request.socket.send_json(msg)
    reply = await request.socket.recv_json()
    current_app.flowapi_logger.debug(f"Received reply: {reply}",
                                     request_id=request.request_id)

    if reply["status"] == "error":
        try:
            # TODO: check that this path is fully tested!
            query_state = reply["payload"]["query_state"]
            if query_state in ("executing", "queued"):
                return {}, 202
            elif query_state == "errored":
                return (
                    {
                        "status": "Error",
                        "msg": reply["msg"]
                    },
                    403,
                )  # TODO: should this really be 403?
            elif query_state in ("awol", "known"):
                return {"status": "Error", "msg": reply["msg"]}, 404
            else:
                return (
                    {
                        "status": "Error",
                        "msg": f"Unexpected query state: {query_state}",
                    },
                    500,
                )
        except KeyError:
            return {"status": "error", "msg": reply["msg"]}, 500
    else:
        sql = reply["payload"]["sql"]
        if filetype == "json":
            results_streamer = stream_with_context(stream_result_as_json)(
                sql, additional_elements={
                    "query_id": query_id
                })
            mimetype = "application/json"
        elif filetype == "csv":
            results_streamer = stream_with_context(stream_result_as_csv)(sql)
            mimetype = "text/csv"
        elif filetype == "geojson":
            current_user.can_get_geography(
                aggregation_unit=reply["payload"]["aggregation_unit"])
            results_streamer = stream_with_context(stream_result_as_json)(
                sql,
                result_name="features",
                additional_elements={
                    "type": "FeatureCollection"
                },
            )
            mimetype = "application/geo+json"
        else:
            return {"status": "error", "msg": "Invalid file format"}, 400

        current_app.flowapi_logger.debug(
            f"Returning result of query {query_id}.",
            request_id=request.request_id)
        return (
            results_streamer,
            200,
            {
                "Transfer-Encoding": "chunked",
                "Content-Disposition":
                f"attachment;filename={query_id}.{filetype}",
                "Content-type": mimetype,
            },
        )
Exemplo n.º 8
0
async def get_query_result(query_id):
    """
    Get the output of a completed query.
    ---
    get:
      parameters:
        - in: path
          name: query_id
          required: true
          schema:
            type: string
      responses:
        '200':
          content:
            application/json:
              schema:
                type: object
          description: Results returning.
        '202':
          content:
            application/json:
              schema:
                type: object
          description: Request accepted.
        '401':
          description: Unauthorized.
        '403':
          content:
            application/json:
              schema:
                type: object
          description: Token does not grant results access to this query or spatial aggregation unit.
        '404':
          description: Unknown ID
        '500':
          description: Server error.
      summary: Get the output of query
    """
    await current_user.can_get_results_by_query_id(query_id=query_id)
    msg = {
        "request_id": request.request_id,
        "action": "get_sql_for_query_result",
        "params": {
            "query_id": query_id
        },
    }
    request.socket.send_json(msg)
    reply = await request.socket.recv_json()
    current_app.flowapi_logger.debug(f"Received reply: {reply}",
                                     request_id=request.request_id)

    if reply["status"] == "error":
        # TODO: check that this path is fully tested!
        query_state = reply["payload"]["query_state"]
        if query_state in ("executing", "queued"):
            return jsonify({}), 202
        elif query_state == "errored":
            return (
                jsonify({
                    "status": "Error",
                    "msg": reply["msg"]
                }),
                403,
            )  # TODO: should this really be 403?
        elif query_state in ("awol", "known"):
            return (jsonify({"status": "Error", "msg": reply["msg"]}), 404)
        else:
            return (
                jsonify({
                    "status": "Error",
                    "msg": f"Unexpected query state: {query_state}"
                }),
                500,
            )
    else:
        sql = reply["payload"]["sql"]
        results_streamer = stream_with_context(stream_result_as_json)(
            sql, additional_elements={
                "query_id": query_id
            })
        mimetype = "application/json"

        current_app.flowapi_logger.debug(
            f"Returning result of query {query_id}.",
            request_id=request.request_id)
        return (
            results_streamer,
            200,
            {
                "Transfer-Encoding": "chunked",
                "Content-Disposition": f"attachment;filename={query_id}.json",
                "Content-type": mimetype,
            },
        )