Skip to content

Commit 9b31fa2

Browse files
authored
Merge pull request #1020 from fiedlr/afi-cancel-tokens
feat: cancel tokens bouncing
2 parents 5f39ae0 + a60c5a6 commit 9b31fa2

File tree

2 files changed

+46
-5
lines changed

2 files changed

+46
-5
lines changed

gooddata-sdk/gooddata_sdk/compute/model/execution.py

+23-5
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,14 @@ def __init__(
6060
filters: Optional[list[Filter]],
6161
dimensions: list[TableDimension],
6262
totals: Optional[list[TotalDefinition]] = None,
63+
is_cancellable: bool = False,
6364
) -> None:
6465
self._attributes = attributes or []
6566
self._metrics = metrics or []
6667
self._filters = filters or []
6768
self._dimensions = [dim for dim in dimensions if dim.item_ids is not None]
6869
self._totals = totals
70+
self._is_cancellable = is_cancellable
6971

7072
@property
7173
def attributes(self) -> list[Attribute]:
@@ -98,6 +100,10 @@ def is_one_dim(self) -> bool:
98100
def is_two_dim(self) -> bool:
99101
return len(self.dimensions) == 2
100102

103+
@property
104+
def is_cancellable(self) -> bool:
105+
return self._is_cancellable
106+
101107
def _create_value_sort_key(self, sort_key: dict) -> models.SortKey:
102108
sort_key_value = sort_key["value"]
103109
return models.SortKey(
@@ -296,13 +302,15 @@ def __init__(
296302
api_client: GoodDataApiClient,
297303
workspace_id: str,
298304
execution_response: models.AfmExecutionResponse,
305+
cancel_token: Optional[str] = None,
299306
):
300307
self._api_client = api_client
301308
self._actions_api = self._api_client.actions_api
302309
self._workspace_id = workspace_id
303310

304311
self._exec_response: models.ExecutionResponse = execution_response["execution_response"]
305312
self._afm_exec_response = execution_response
313+
self._cancel_token = cancel_token
306314

307315
@property
308316
def workspace_id(self) -> str:
@@ -316,6 +324,10 @@ def result_id(self) -> str:
316324
def dimensions(self) -> Any:
317325
return self._exec_response["dimensions"]
318326

327+
@property
328+
def cancel_token(self) -> Optional[str]:
329+
return self._cancel_token
330+
319331
def read_result(self, limit: Union[int, list[int]], offset: Union[None, int, list[int]] = None) -> ExecutionResult:
320332
"""
321333
Reads from the execution result.
@@ -335,6 +347,7 @@ def read_result(self, limit: Union[int, list[int]], offset: Union[None, int, lis
335347
limit=_limit,
336348
_check_return_type=False,
337349
_return_http_data_only=False,
350+
**({"x_gdc_cancel_token": self.cancel_token} if self.cancel_token else {}),
338351
)
339352
custom_headers = self._api_client.custom_headers
340353
if "X-GDC-TRACE-ID" in custom_headers and "X-GDC-TRACE-ID" in http_headers:
@@ -351,7 +364,7 @@ def __str__(self) -> str:
351364
return self.__repr__()
352365

353366
def __repr__(self) -> str:
354-
return f"BareExecutionResponse(workspace_id={self.workspace_id}, result_id={self.result_id})"
367+
return f"BareExecutionResponse(workspace_id={self.workspace_id}, result_id={self.result_id}, cancel_token={self.cancel_token})"
355368

356369

357370
class Execution:
@@ -367,12 +380,11 @@ def __init__(
367380
workspace_id: str,
368381
exec_def: ExecutionDefinition,
369382
response: models.AfmExecutionResponse,
383+
cancel_token: Optional[str] = None,
370384
):
371385
self._exec_def = exec_def
372386
self._bare_exec_response = BareExecutionResponse(
373-
api_client=api_client,
374-
workspace_id=workspace_id,
375-
execution_response=response,
387+
api_client=api_client, workspace_id=workspace_id, execution_response=response, cancel_token=cancel_token
376388
)
377389

378390
@property
@@ -395,6 +407,10 @@ def result_id(self) -> str:
395407
def dimensions(self) -> Any:
396408
return self.bare_exec_response._exec_response["dimensions"]
397409

410+
@property
411+
def cancel_token(self) -> Optional[str]:
412+
return self.bare_exec_response.cancel_token
413+
398414
def get_labels_and_formats(self) -> tuple[dict[str, str], dict[str, str]]:
399415
"""
400416
Extracts labels and custom measure formats from the execution response.
@@ -425,7 +441,9 @@ def __str__(self) -> str:
425441
return self.__repr__()
426442

427443
def __repr__(self) -> str:
428-
return f"Execution(workspace_id={self.workspace_id}, result_id={self.bare_exec_response.result_id})"
444+
return (
445+
f"Execution(workspace_id={self.workspace_id}, result_id={self.result_id}, cancel_token={self.cancel_token})"
446+
)
429447

430448

431449
# Originally ExecutionResponse contained also ExecutionDefinition which was not correct, therefore Execution class was

gooddata-sdk/gooddata_sdk/compute/service.py

+23
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import logging
55

6+
from gooddata_api_client.model.afm_cancel_tokens import AfmCancelTokens
67
from gooddata_api_client.model.chat_history_request import ChatHistoryRequest
78
from gooddata_api_client.model.chat_history_result import ChatHistoryResult
89
from gooddata_api_client.model.chat_request import ChatRequest
@@ -41,6 +42,7 @@ def for_exec_def(self, workspace_id: str, exec_def: ExecutionDefinition) -> Exec
4142
workspace_id=workspace_id,
4243
exec_def=exec_def,
4344
response=response,
45+
cancel_token=response.headers.get("X-GDC-CANCEL-TOKEN") if exec_def.is_cancellable else None,
4446
)
4547

4648
def retrieve_result_cache_metadata(self, workspace_id: str, result_id: str) -> ResultCacheMetadata:
@@ -107,3 +109,24 @@ def ai_chat_history_reset(self, workspace_id: str) -> None:
107109
"""
108110
chat_history_request = ChatHistoryRequest(reset=True)
109111
self._actions_api.ai_chat_history(workspace_id, chat_history_request, _check_return_type=False)
112+
113+
def cancel_executions(self, executions: list[Execution]) -> None:
114+
"""
115+
Try to cancel given executions using the cancel api endpoint.
116+
117+
*Note that this is currently a noop, we will be enabling this functionality soon.*
118+
119+
Args:
120+
executions: list of executions to send for cancellation
121+
"""
122+
workspace_to_tokens: dict[str, set[str]] = {}
123+
124+
for execution in executions:
125+
if not workspace_to_tokens[execution.workspace_id]:
126+
workspace_to_tokens[execution.workspace_id] = set()
127+
128+
if execution.cancel_token:
129+
workspace_to_tokens[execution.workspace_id].add(execution.cancel_token)
130+
131+
for workspace_id, token_ids in workspace_to_tokens.items():
132+
self._actions_api.cancel_executions(workspace_id, AfmCancelTokens(list(token_ids)))

0 commit comments

Comments
 (0)