diff --git a/tableauserverclient/server/endpoint/workbooks_endpoint.py b/tableauserverclient/server/endpoint/workbooks_endpoint.py index 5f9695829..218a4016f 100644 --- a/tableauserverclient/server/endpoint/workbooks_endpoint.py +++ b/tableauserverclient/server/endpoint/workbooks_endpoint.py @@ -14,6 +14,7 @@ from tableauserverclient.server.endpoint.exceptions import ( InternalServerError, MissingRequiredFieldError, + ServerResponseError, UnsupportedAttributeError, ) from tableauserverclient.server.endpoint.permissions_endpoint import _PermissionsEndpoint @@ -125,7 +126,7 @@ def get_by_id(self, workbook_id: str) -> WorkbookItem: return WorkbookItem.from_response(server_response.content, self.parent_srv.namespace)[0] @api(version="2.8") - def refresh(self, workbook_item: Union[WorkbookItem, str], incremental: bool = False) -> JobItem: + def refresh(self, workbook_item: Union[WorkbookItem, str], incremental: bool = False) -> JobItem | None: """ Refreshes the extract of an existing workbook. @@ -138,13 +139,19 @@ def refresh(self, workbook_item: Union[WorkbookItem, str], incremental: bool = F Returns ------- - JobItem - The job item. + JobItem | None + The job item, or None if a refresh job is already queued for this workbook. """ id_ = getattr(workbook_item, "id", workbook_item) url = f"{self.baseurl}/{id_}/refresh" refresh_req = RequestFactory.Task.refresh_req(incremental, self.parent_srv) - server_response = self.post_request(url, refresh_req) + try: + server_response = self.post_request(url, refresh_req) + except ServerResponseError as e: + if e.code.startswith("409") and "already" in e.detail: + logger.warning(f"{e.summary} {e.detail}") + return None + raise new_job = JobItem.from_response(server_response.content, self.parent_srv.namespace)[0] return new_job diff --git a/test/assets/workbook_refresh_duplicate.xml b/test/assets/workbook_refresh_duplicate.xml new file mode 100644 index 000000000..eca4b4bcc --- /dev/null +++ b/test/assets/workbook_refresh_duplicate.xml @@ -0,0 +1,3 @@ + + +Resource ConflictJob for \'extract\' is already queued. Not queuing a duplicate. \ No newline at end of file diff --git a/test/test_workbook.py b/test/test_workbook.py index e6e807f89..b210e8402 100644 --- a/test/test_workbook.py +++ b/test/test_workbook.py @@ -34,6 +34,7 @@ PUBLISH_XML = TEST_ASSET_DIR / "workbook_publish.xml" PUBLISH_ASYNC_XML = TEST_ASSET_DIR / "workbook_publish_async.xml" REFRESH_XML = TEST_ASSET_DIR / "workbook_refresh.xml" +WORKBOOK_REFRESH_DUPLICATE_XML = TEST_ASSET_DIR / "workbook_refresh_duplicate.xml" REVISION_XML = TEST_ASSET_DIR / "workbook_revision.xml" UPDATE_XML = TEST_ASSET_DIR / "workbook_update.xml" UPDATE_PERMISSIONS = TEST_ASSET_DIR / "workbook_update_permissions.xml" @@ -178,6 +179,20 @@ def test_refresh_id(server: TSC.Server) -> None: server.workbooks.refresh("3cc6cd06-89ce-4fdc-b935-5294135d6d42") +def test_refresh_already_running(server: TSC.Server) -> None: + server.version = "2.8" + server.workbooks.baseurl + response_xml = WORKBOOK_REFRESH_DUPLICATE_XML.read_text() + with requests_mock.mock() as m: + m.post( + server.workbooks.baseurl + "/3cc6cd06-89ce-4fdc-b935-5294135d6d42/refresh", + status_code=409, + text=response_xml, + ) + refresh_job = server.workbooks.refresh("3cc6cd06-89ce-4fdc-b935-5294135d6d42") + assert refresh_job is None + + def test_refresh_object(server: TSC.Server) -> None: server.version = "2.8" server.workbooks.baseurl