def _run_async(self, command: ChartDataCommand) -> Response: """ Execute command as an async query. """ # First, look for the chart query results in the cache. try: result = command.run(force_cached=True) except ChartDataCacheLoadError: result = None # type: ignore already_cached_result = result is not None # If the chart query has already been cached, return it immediately. if already_cached_result: return self.send_chart_response(result) # Otherwise, kick off a background job to run the chart query. # Clients will either poll or be notified of query completion, # at which point they will call the /data/<cache_key> endpoint # to retrieve the results. try: command.validate_async_request(request) except AsyncQueryTokenException: return self.response_401() result = command.run_async(g.user.get_id()) return self.response(202, **result)
def data(self) -> Response: """ Takes a query context constructed in the client and returns payload data response for the given query. --- post: description: >- Takes a query context constructed in the client and returns payload data response for the given query. requestBody: description: >- A query context consists of a datasource from which to fetch data and one or many query objects. required: true content: application/json: schema: $ref: "#/components/schemas/ChartDataQueryContextSchema" responses: 200: description: Query result content: application/json: schema: $ref: "#/components/schemas/ChartDataResponseSchema" 202: description: Async job details content: application/json: schema: $ref: "#/components/schemas/ChartDataAsyncResponseSchema" 400: $ref: '#/components/responses/400' 401: $ref: '#/components/responses/401' 500: $ref: '#/components/responses/500' """ json_body = None if request.is_json: json_body = request.json elif request.form.get("form_data"): # CSV export submits regular form data try: json_body = json.loads(request.form["form_data"]) except (TypeError, json.JSONDecodeError): pass if json_body is None: return self.response_400(message=_("Request is not JSON")) try: command = ChartDataCommand() query_context = command.set_query_context(json_body) command.validate() except QueryObjectValidationError as error: return self.response_400(message=error.message) except ValidationError as error: return self.response_400( message=_("Request is incorrect: %(error)s", error=error.normalized_messages())) # TODO: support CSV, SQL query and other non-JSON types if (is_feature_enabled("GLOBAL_ASYNC_QUERIES") and query_context.result_format == ChartDataResultFormat.JSON and query_context.result_type == ChartDataResultType.FULL): try: command.validate_async_request(request) except AsyncQueryTokenException: return self.response_401() result = command.run_async(g.user.get_id()) return self.response(202, **result) return self.get_data_response(command)
def data(self) -> Response: """ Takes a query context constructed in the client and returns payload data response for the given query. --- post: description: >- Takes a query context constructed in the client and returns payload data response for the given query. requestBody: description: >- A query context consists of a datasource from which to fetch data and one or many query objects. required: true content: application/json: schema: $ref: "#/components/schemas/ChartDataQueryContextSchema" responses: 200: description: Query result content: application/json: schema: $ref: "#/components/schemas/ChartDataResponseSchema" 202: description: Async job details content: application/json: schema: $ref: "#/components/schemas/ChartDataAsyncResponseSchema" 400: $ref: '#/components/responses/400' 401: $ref: '#/components/responses/401' 500: $ref: '#/components/responses/500' """ json_body = None if request.is_json: json_body = request.json elif request.form.get("form_data"): # CSV export submits regular form data try: json_body = json.loads(request.form["form_data"]) except (TypeError, json.JSONDecodeError): pass if json_body is None: return self.response_400(message=_("Request is not JSON")) try: command = ChartDataCommand() query_context = command.set_query_context(json_body) command.validate() except QueryObjectValidationError as error: return self.response_400(message=error.message) except ValidationError as error: return self.response_400( message=_("Request is incorrect: %(error)s", error=error.normalized_messages())) # TODO: support CSV, SQL query and other non-JSON types if (is_feature_enabled("GLOBAL_ASYNC_QUERIES") and query_context.result_format == ChartDataResultFormat.JSON and query_context.result_type == ChartDataResultType.FULL): # First, look for the chart query results in the cache. try: result = command.run(force_cached=True) except ChartDataCacheLoadError: result = None # type: ignore already_cached_result = result is not None # If the chart query has already been cached, return it immediately. if already_cached_result: return self.send_chart_response(result) # Otherwise, kick off a background job to run the chart query. # Clients will either poll or be notified of query completion, # at which point they will call the /data/<cache_key> endpoint # to retrieve the results. try: command.validate_async_request(request) except AsyncQueryTokenException: return self.response_401() result = command.run_async(g.user.get_id()) return self.response(202, **result) return self.get_data_response(command)