Luminesce has a SqlBackground
API you can use to execute a long-running Luminesce SQL query and monitor its progress. You can use this information to handle errors and timeouts.
To use the SqlBackground
API, it’s important to perform all of the following steps:
Step 1: Start your query
Call the the StartQuery API for your LUSID domain, passing in your API token and:
A
queryName
you can view in logs and when using Sys.Logs.HcQueryStart.A
timeoutSeconds
value specifying the maximum time the query can run for.A
keepForSeconds
value specifying how long the result is stored for.Any
scalarParameters
as key-value pairs to use in the execution.Your Luminesce SQL query as the request body.
For example, to start a query that upserts a large quantity of transactions to multiple portfolios:
curl -X PUT "https://<your-domain>.lusid.com/honeycomb/api/SqlBackground"
-H "Authorization: Bearer <your-API-access-token>"
-d "
@txns = values
('US-Equities', 'TXN-123', 'Buy', 100, 250, 25000, 'AMGN', 'LUID_00003DFS', 750),
('Global-Portfolio', 'TXN-124', 'StockIn', 100, 200, 20000, 'AAPL', 'LUID_00003DG1', 600),
('Global-Portfolio', 'TXN-125', 'Sell', 100, 800, 80000, 'INTC', 'LUID_00003DFJ', 2400);
@table_of_data = select 'Finbourne-Examples' as PortfolioScope, column1 as PortfolioCode, column2 as TxnId, column3 as Type,
#2024-09-18# as TransactionDate, #2024-09-19# as SettlementDate, column4 as Units, column5 as TradePrice, column6 as TotalConsideration,
'GBP' as SettlementCurrency, column7 as Ticker, column8 as ClientInternal, column9 as BrokerCommission
from @txns;
select * from Lusid.Portfolio.Txn.Writer where ToWrite = @table_of_data;"
Part of a successful response is as follows, meaning the query was successfully parsed. Note the executionId
which you must use to monitor the query going forward:
{
"executionId": "f2c1fb86-cb4e-4d4c-a555-3da4cef751e0",
"progress": {
"relation": "Progress",
"href": "/api/SqlBackground/f2c1fb86-cb4e-4d4c-a555-3da4cef751e0",
"description": "Gets the current state and user-presentable progress information",
"method": "GET"
},
"cancel": {
"relation": "Cancel",
"href": "/api/SqlBackground/f2c1fb86-cb4e-4d4c-a555-3da4cef751e0",
"description": "Cancels (if running) or clears the data from (if completed) a previously started query",
"method": "DELETE"
},
"fetchJson": {
"relation": "FetchJson",
"href": "/api/SqlBackground/f2c1fb86-cb4e-4d4c-a555-3da4cef751e0/json",
"description": "Gets the resulting data (or error information on failure) in Json format",
"method": "GET"
},
...
}
Step 2: Check query execution progress
After you successfully start the query execution, you can call the GetProgressOf API, passing in the executionId
to the URL, to check on its progress.
We strongly recommend you use information from the response for monitoring and handling the execution of your long-running queries. The GetProgressOf
API response is invaluable for investigating issues if your queries do not execute as expected.
For example, to check on the progress of the query sent in step 1:
curl -X GET "https://<your-domain>.lusid.com/honeycomb/api/SqlBackground/f2c1fb86-cb4e-4d4c-a555-3da4cef751e0"
-H "Authorization: Bearer <your-API-access-token>"
Part of a successful response is as follows:
{
"hasData": true,
"rowCount": 3,
"status": "RanToCompletion",
"state": "Serialized",
"progress": "11:57:21.929 >> Progress / QueryOrchestrator >> @txns [1] -> calculating ...\n11:57:21.957 >> Progress / QueryOrchestrator >> @txns -> 3 rows in [0.6738ms + 27ms + 0.0143ms]\n11:57:21.957 >> Progress / QueryOrchestrator >> @table_of_data [2] -> calculating ...\n11:57:21.981 >> Progress / QueryOrchestrator >> @table_of_data -> 3 rows in [0.6243ms + 23ms + 0.0137ms]\n11:57:22.002 >> Progress / QueryOrchestrator >> Lusid.Portfolio.Txn.Writer [PortfolioScope, PortfolioCode, DisplayName, Txn...]\n11:57:23.144 >> Warning / ToWrite >> The following columns are understood and passed in: PortfolioScope, PortfolioCode, TxnId, Type, TransactionDate, SettlementDate, Units, TradePrice, TotalConsideration, SettlementCurrency, Ticker, ClientInternal\nThe following columns are understood yet not passed in: TradePriceType, TradeCurrency, ExchangeRate, CounterpartyId, Source, BondInterest, TradeToPortfolioRate, OrderScope, OrderCode, AllocationScope, AllocationCode, WriteAction, LusidInstrumentId, Isin, Sedol, Cusip, Figi, CompositeFigi, ShareClassFigi, Wertpapier, RIC, QuotePermId, EdiKey\nThe following columns are passed in yet are not understood (so skipped): BrokerCommission\n11:57:25.444 >> Progress / Lusid.Portfolio.Txn.Writer >> 1 transactions written so far\n11:57:26.059 >> Progress / QueryOrchestrator >> Lusid.Portfolio.Txn.Writer -> 3 rows in [21ms + 4.052s + 3.4746ms]\n11:57:26.089 >> Progress / QueryOrchestrator >> \n@txns = values\n('US-Equities', 'TXN-123', 'Buy', 100, 250, 25000, 'AMGN', 'LUID_00003DFS', 750),\n('Global-Portfolio', 'TXN-124', 'StockIn', 100, 200, 20000, 'AAPL', 'LUID_00003DG1', 600),\n('Global-Portfolio', 'TXN-125', 'Sell', 100, 800, 80000, 'INTC', 'LUID_00003DFJ', 2400);\n\n@table_of_data = select 'Finbourne-Examples' as PortfolioScope, column1 as PortfolioCode, column2 as TxnId, column3 as Type,\n#2024-09-18# as TransactionDate, #2024-09-19# as SettlementDate, column4 as Units, column5 as TradePrice, column6 as TotalConsideration,\n'GBP' as SettlementCurrency, column7 as Ticker, column8 as ClientInternal, column9 as BrokerCommission\nfrom @txns;\n\nselect * from Lusid.Portfolio.Txn.Writer where ToWrite = @table_of_data;\n\nRows : 3\nData Volume : 798 B\n\nPrep : 208.3708 ms\nProviders : 4131.1449 ms\nMerge/Sql : 0.3232 ms\nFillTable : 27.5036 ms\n(total) : 4367.3425 ms\n\nSession Id : c649a7d7-3b05-4d76-862b-738573387a5e\nExecution Id : 8b61dae9-e29e-4793-b052-cacd86624690\nExt. Ex. Id : 0HN6PD7QFTS9M:00000007\nScalar Param : null\nClient : <your-domain>\nClient Id : 0oa7draltjzKvjCz92p7\nUser Id : 00uji4twb4jDcHGjN2p7\nUser Type : Personal\nApi Version : 1.16.625.0\n\nDependency & Execution details:\n\n. | 4.334s|\n@anonymous_0 => @txns | | | \n@txns => @table_of_data | | | -> 3 row(s)\n@table_of_data | || | -> 3 row(s)\nLusid.Portfolio.Txn.Writer | ||>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>| -> 3 row(s)\nQuery Coordinator |**|--------------------------------------------------------| -> 3 row(s)\n\n",
"feedback": [
{
"when": "2024-09-20T11:57:21.9296540Z",
"sessionId": "c649a7d7-3b05-4d76-862b-738573387a5e",
"executionId": "8b61dae9-e29e-4793-b052-cacd86624690",
"level": "Progress",
"sender": "QueryOrchestrator",
"messageTemplate": "{Variable} [{Id}] -> calculating ...",
"propertyValues": [
"@txns",
1
],
"message": "@txns [1] -> calculating ..."
},
...
],
"query": "@txns = values\n('US-Equities', 'TXN-123', 'Buy', 100, 250, 25000, 'AMGN', 'LUID_00003DFS', 750),\n('Global-Portfolio', 'TXN-124', 'StockIn', 100, 200, 20000, 'AAPL', 'LUID_00003DG1', 600),\n('Global-Portfolio', 'TXN-125', 'Sell', 100, 800, 80000, 'INTC', 'LUID_00003DFJ', 2400);\n\n@table_of_data = select 'Finbourne-Examples' as PortfolioScope, column1 as PortfolioCode, column2 as TxnId, column3 as Type,\n#2024-09-18# as TransactionDate, #2024-09-19# as SettlementDate, column4 as Units, column5 as TradePrice, column6 as TotalConsideration,\n'GBP' as SettlementCurrency, column7 as Ticker, column8 as ClientInternal, column9 as BrokerCommission\nfrom @txns;\n\nselect * from Lusid.Portfolio.Txn.Writer where ToWrite = @table_of_data;",
"columnsAvailable": [
{
"isPrimaryKey": false,
"isMain": false,
"isRequiredByProvider": false,
"name": "PortfolioScope",
"type": "Text",
"displayName": "Portfolio Scope",
"conditionUsage": "None"
},
...
]
}
The state
and status
fields in the response can be particularly useful:
State
The state
field in the response tells you the current state of the Luminesce SQL query. The following list provides more information on each state
:
New
: The query is not yet fully initialised.Running
: Currently executing the query.Errored
: Error when executing query.Cancelled
: Cancelled when executing the query.Executed
: Query successfully executed.ExecutedNoSerializationRequired
: Query successfully executed and no serialization was required.Serialized
: Query executed and written to cloud storage cache.SerializationFailed
: Query executed but failed to be written to cloud storage cache.AttemptingToDeserialize
: Query executed, successfully cached and now being read from cloud storage cache.Loaded
: Query executed, successfully cached and now being loaded.Cleared
: Query passed its expiry limit and has been deleted.Disposed
: Query no longer available from storage.OwnerTerminated
: AWS node was forced to terminate the query execution. Another pod may pick this up.
Status
The status
field in the response tells you to some extent if the query has succeeded or failed, though note the state
field (above) is more informative. You could choose to handle WaitingForActivation
, Faulted
and Cancelled
in a loop to achieve the desired behaviour.
The following list provides more information on each status
:
Created
: Query execution is in progress.WaitingToRun
: Query execution is in progress.Running
: Query execution is in progress.WaitingForChildrenToComplete
: Query execution is in progress.WaitingForActivation
: Query execution is in progress.Canceled
: User cancelled the query execution.Faulted
: Something went wrong; further information can be retrieved from the response JSON. See step 3 to retrieve an end failure message.RanToCompletion
: Query has completed successfully. A table of data is available for downloading in a variety of formats. See step 3.
Unexpected timeouts at or beyond 30 minutes
Note that a query may error with a
Timeout
if the query either:
Runs for longer than 30 minutes (due to potential Luminesce query engine interruption).
Has any single provider call that takes longer than 30 minutes (due to potential provider interruption).
This may occasionally happen even if the
PRAGMA TimeoutSec = N;
and/or thetimeoutSeconds
parameter is set to more than 1800.This is because cloud infrastructure for excessively long running operations cannot be guaranteed. Luminesce implements many strategies to ensure runtimes of up to 30 minutes are as likely to complete as possible. For runtimes of 30 minutes or more, cloud interruption events and continuous deployment operations are allowed to interrupt such queries.
Runtimes of over 8 hours are not supported.
Step 3: Retrieve your results
Once your GetProgressOf
response has a status
of RanToCompletion
, you can call the FetchQueryResult<format>
API to return the query results as a table of data in your preferred format. You can also use this API to retrieve an end failure message if your response has a status
of Faulted
.
Currently, APIs are available to retrieve results in the following formats:
For example, to return the results of the query sent in step 1 as a table of data in a CSV format, you can call the FetchQueryResultCsv API:
curl -X GET "https://<your-domain>.lusid.com/honeycomb/api/SqlBackground/f2c1fb86-cb4e-4d4c-a555-3da4cef751e0/csv?download=true"
-H "Accept: application/json, text/plain, text/json"
-H "Authorization: Bearer <your-API-access-token>"
429 errors
For
FetchQueryResult
API requests, you are likely to receive at least one429
response. A429
response indicates the query is still running or that data is being serialized.You can retry your request until you receive a non-
429
response. You should anticipate and handle this response; expand the following to see an example Python script:
Click to expand Python example
# 1.1 Setup
import luminesce
import time
import string
import random
# 1.2 Imports
from luminesce.exceptions import ApiException
from luminesce import (
ApiClientFactory,
SqlBackgroundExecutionApi
)
# 1.3 Class setup
class Response:
def __init__(self, response_body, error, should_retry):
self.response_body = response_body
self.error = error
self.should_retry = should_retry
# 1.4 Method setup
async def call_and_handle_response(func, additional_error_handling={}, extended_wait=10, call_threshold=5, call_count=0,
**kwargs):
'''
Handles a response from a call to a Luminesce SqlBackground API.
Parameters:
func (kwargs -> BackgroundApiResponse): Api call to invoke
additional_error_handling (dict): any additional error handling for this api call
extended_wait (int): How long to wait if we were rate-limited
call_count (int): how many calls have been made to this api?
call_threshold (int): how many calls can be made to this api before we give up?
kwargs: to pass to func
Returns:
Response object
'''
def handle_status_codes(additional_cases):
async def on_unexpected_error(error):
return Response(None, error, False) # Or we can just `raise` here
async def on_standard_error(error):
print(f"{func} failed with code: {error.status}. Reason: {error.reason}")
return Response(None, error, False)
async def on_rate_limit(error):
print(f"On func: {func} - rate limited - waiting: {extended_wait}s before retrying")
time.sleep(extended_wait)
return await call_and_handle_response(func, additional_error_handling, extended_wait, call_count + 1,
kwargs)
standard_cases = {
401: on_standard_error,
403: on_standard_error,
429: on_rate_limit
}
standard_cases.update(additional_cases)
return lambda ex: standard_cases.get(ex.status, on_unexpected_error)
async def handle_response(task, onException):
try:
task_result = await task
return Response(task_result, None, False)
except ApiException as e:
return await onException(e)(e)
print(f"On func: {func} - call number: {call_count}")
if call_count >= call_threshold:
return Response(None, ApiException(f"{func} exhausted retries ({call_threshold})"), False)
thread = func(**kwargs)
api_response_task = thread.get()
# above, ApplyResult -> coroutine
return await handle_response(api_response_task, handle_status_codes(additional_error_handling))
async def start_luminesce_background_query(api_instance, **kwargs):
'''
Start a Luminesce backgroundquery
Parameters:
api_instance (SqlBackgroundExecutionApi): api client for sql background api
kwargs - args needed for the startquery api call
Returns:
Response object
'''
async def on_parse_error(error):
print(f"StartQuery - for query: {kwargs['query_name']} failed with a parse error")
print(f"Details: {error.body}")
return Response(None, error, False)
error_cases_for_startquery = {
400: on_parse_error
}
return await call_and_handle_response(api_instance.start_query_with_http_info,
additional_error_handling=error_cases_for_startquery, **kwargs)
async def get_progress_of_luminesce_background_query(api_instance, longer_wait, **kwargs):
'''
Gets progress of a Luminesce backgroundquery
Parameters:
api_instance (SqlBackgroundExecutionApi): api client for sql background api
longer_wait = if we are rate limited, how much longer to wait?
kwargs - args needed for the getprogress api call
Returns:
Response object
'''
async def on_no_query(error):
print(f"GetProgressOf - for query: {kwargs['execution_id']} failed with no query found")
print(f"Details: {error.body}")
return Response(None, error, False)
error_cases_for_getprogressof = {
404: on_no_query
}
return await call_and_handle_response(api_instance.get_progress_of_with_http_info,
additional_error_handling=error_cases_for_getprogressof,
extended_wait=longer_wait, **kwargs)
def should_retry_query(last_response):
'''
Should we retry a query based on the outcome of GetProgressOf?
We want to retry in the case of infrastructure failures that we are able to see from GetProgressOf responses
Parameters:
last_response (ApiResponse body): tuple of the outcome of the last poll
Returns:
should_retry (bool): True if the query should be retried
'''
response_dict = last_response.data.to_dict()
status_from_last_poll = response_dict['status'].value
progress_from_last_poll = response_dict['progress']
return status_from_last_poll == 'Faulted' and 'RETRIEVAL STOP POLLING' in progress_from_last_poll
def construct_execution_id():
'''
Generates a random execution id for the background query
:return: (string) execution id to use
'''
def get_part(n):
return ''.join(random.choices(string.hexdigits, k=n))
separator = '-'
parts = []
parts.append(get_part(8))
parts.append(get_part(4))
parts.append(get_part(4))
parts.append(get_part(4))
parts.append(get_part(12))
constructed_execution_id = separator.join(parts).lower()
print(f"Running query with constructed execution id: {constructed_execution_id}")
return constructed_execution_id
async def wait_for_background_query(
api_instance,
execution_id,
delay_s_between_polls=7,
longer_delay_s_between_polls=10):
'''
Wait for a Luminesce backgroundquery to complete
Polls the GetProgressOf endpoint for as long as the query is in an incomplete 'WaitingForActivation' state.
Uses the states provided by .NET themselves: https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskstatus?view=net-6.0
Will throw if forbidden/GetProgressOf itself fails
Parameters:
api_instance (SqlBackgroundExecutionApi): api client for sql background api
execution_id (string): id of Luminesce query whose completion we are monitoring
delay_s_between_polls (int): time to wait between polling for progress of a query. Defaults: 2s
longer_delay_s_between_polls (int): if rate-limited, how long to wait before polling next. Defaults: 10s
Returns:
Response object
'''
status = "WaitingForActivation"
idx = 0
progress = None
while status == "WaitingForActivation":
print(f"Polling progress of: {execution_id} - iteration: {idx}")
progress = await get_progress_of_luminesce_background_query(
api_instance,
longer_wait=longer_delay_s_between_polls,
execution_id=execution_id,
async_req=True)
if progress.response_body is None:
return progress
response_dict = progress.response_body.data.to_dict()
status = response_dict['status'].value
if not str(progress.response_body.status_code).startswith("2"):
print(f"ODD STATUS: {status}")
time.sleep(delay_s_between_polls)
idx += 1
if should_retry_query(progress.response_body):
print(
f"For query with execution id: {execution_id}, GetProgressOf suggests an infrastructure failure. Retrying...")
progress.should_retry = True
return progress
async def fetch_query_result(api_instance, last_progress, retry_if_undetermined=True, **kwargs):
'''
Returns the result of a Luminesce query as json.
Parameters:
api_instance (SqlBackgroundExecutionApi): background api instance
last_progress - Response object, the last Response received from GetProgressOf
retry_if_undetermined - if the status code is Gone - and we can't see the response body, should we retry the whole query?
kwargs - needed for fetching query result
Returns:
Response object
'''
async def on_no_query(error):
print(f"FetchQueryResult - for query: {kwargs['execution_id']} failed with no query found")
print(f"Details: {error.body}")
return Response(None, error, False)
async def on_query_error(error):
print(f"FetchQueryResult - for query: {kwargs['execution_id']} failed with an error in the query")
print(f"Details: {error.body}")
return Response(None, error, False)
async def on_query_gone(error):
print(
f"FetchQueryResult - for query: {kwargs['execution_id']} - failed because response is gone. Retrying? {retry_if_undetermined}")
print(f"Last progress state: {last_progress.response_body.data.to_dict()['status'].value}")
return Response(None, error, retry_if_undetermined)
error_cases_for_fetchqueryresult = {
400: on_query_error,
404: on_no_query,
410: on_query_gone
}
return await call_and_handle_response(api_instance.fetch_query_result_json_proper,
additional_error_handling=error_cases_for_fetchqueryresult, **kwargs)
async def run_luminesce_background_query(api_instance, get_sql_str, explicit_execution_id="", query_name="",
max_retries=4, retry_count=0, polling_interval=2):
'''
Main orchestrating method for background query.
Will call methods that start the query, poll for progress and fetch the result
:param api_instance: (SqlBackgroundExecutionApi): background api instance
:param get_sql_str: (Func[string]) Method that returns string of sql to be executed
:param explicit_execution_id: (string) Execution id to use when starting the query
:param query_name: (string) name of query, for finding in logs
:param max_retries: (int) max number of retries allowed for this query. By default retries will happen on 410 GONE errors
:param retry_count: (int) current number of retries that have been done for this query
:param polling_interval: (int) how long to wait between polls of background query progress
:return: (response body) result of background query
'''
def is_error(response):
return response.should_retry or response.response_body is None
async def handle_error(response):
if response.should_retry:
return await run_luminesce_background_query(api_instance, get_sql_str, query_name=query_name,
max_retries=max_retries, retry_count=retry_count + 1,
polling_interval=polling_interval)
if response.response_body is None:
return response.response_body
if retry_count > max_retries:
print(f"Reached max retries ({max_retries}) for query: {query_name}")
return None
# stage 1 - submit the query
start_response = await start_luminesce_background_query(api_instance, body=get_sql_str(),
execution_id=explicit_execution_id, query_name=query_name,
async_req=True)
if is_error(start_response):
return await handle_error(start_response)
# stage 2 - poll
execution_id_in_use = start_response.response_body.data.to_dict()["executionId"]
get_progress_of_response = await wait_for_background_query(api_instance, execution_id=execution_id_in_use,
delay_s_between_polls=polling_interval)
if is_error(get_progress_of_response):
return await handle_error(get_progress_of_response)
# stage 3 - get result
fetch_query_result_response = await fetch_query_result(api_instance, get_progress_of_response,
retry_if_undetermined=True, execution_id=execution_id_in_use,
async_req=True)
if is_error(fetch_query_result_response):
return await handle_error(fetch_query_result_response)
return fetch_query_result_response.response_body
#############
async def main_runner(pre_run_func, main_orchestrator, sql_to_run, execution_id_to_use, query_name, interval):
'''
Call into this method to execute a background query.
:param pre_run_func: (Func) Calls the main_orchestrator (and takes its args). Useful to mock actions like cancelling a query as it runs
:param main_orchestrator: (Func) eg run_luminesce_background_query - responsible for starting/polling/getting result of background query
:param sql_to_run: (Func[string]) - returns string of sql to be executed
:param execution_id_to_use: (string) - execution id to start background query with
:param query_name: (string) - name of query, for logging
:param interval: (int) - seconds, how long to wait between background query polls
:return: (response body) background query result
'''
api_client_factory = ApiClientFactory()
# Enter a context with an instance of the ApiClientFactory to ensure the connection pool is closed after use
async with api_client_factory:
background_api_async_instance = api_client_factory.build(luminesce.SqlBackgroundExecutionApi)
return await pre_run_func(main_orchestrator, sql_to_run, background_api_async_instance, execution_id_to_use, query_name, interval)
#############
async def pre_run_passthrough(runner, sql_to_run, api, execution_id_to_use, query_name, interval):
'''
For the straightforward case, just a pass through that calls runner with the args given
'''
return await runner(api, sql_to_run, explicit_execution_id=execution_id_to_use, query_name=query_name, polling_interval=interval)
If your GetProgressOf
API response (in step 2) contained a status
of RanToCompletion
, a successful response is as follows:
PortfolioScope,PortfolioCode,DisplayName,TxnId,Type,TransactionDate,SettlementDate,Units,TradePrice,TradePriceType,TotalConsideration,TradeCurrency,ExchangeRate,SettlementCurrency,CounterpartyId,Source,BondInterest,TradeToPortfolioRate,OrderScope,OrderCode,AllocationScope,AllocationCode,InstrumentScope,ResolvedLusidInstrumentId,LusidInstrumentId,Isin,Sedol,Cusip,Ticker,ClientInternal,Figi,CompositeFigi,ShareClassFigi,Wertpapier,RIC,QuotePermId,EdiKey,WriteAction,WriteAsAt,WriteErrorCode,WriteError,WriteErrorDetail
Finbourne-Examples,US-Equities,US Equity Portfolio,TXN-123,Buy,2024-09-18,2024-09-19,100,250,Price,25000,,0,GBP,,,,,,,,,default,LUID_00003DFS,,,,,AMGN,LUID_00003DFS,,,,,,,,Upsert,2024-04-10 16:20:17.382,0,,
Finbourne-Examples,Global-Portfolio,Global Portfolio,TXN-124,StockIn,2024-09-18,2024-09-19,100,200,Price,20000,,0,GBP,,,,,,,,,default,LUID_00003DG1,,,,,AAPL,LUID_00003DG1,,,,,,,,Upsert,2024-09-20 11:57:25.548,0,,
Finbourne-Examples,Global-Portfolio,Global Portfolio,TXN-125,Sell,2024-09-18,2024-09-19,100,800,Price,80000,,0,GBP,,,,,,,,,default,LUID_00003DFJ,,,,,INTC,LUID_00003DFJ,,,,,,,,Upsert,2024-09-20 11:57:25.548,0,,
If your GetProgressOf
API response (in step 2) contained a status
of Faulted
, a successful response is formatted as a JSON regardless of the chosen format and contains details on the error.
Cancelling a query
You can cancel a query at any time using the CancelQuery API. When you send a cancellation request:
If the query is still running, the query execution is cancelled.
If the query has finished running, you can no longer retrieve query data.
For example, to cancel the query from step 1:
curl -X DELETE "https://<your-domain>.lusid.com/honeycomb/api/SqlBackground/f2c1fb86-cb4e-4d4c-a555-3da4cef751e0"
-H "accept: text/plain"
-H "Authorization: Bearer <your-API-access-token>"