Skip to content

Expose refreshExtractTriggered on SubscriptionItem - #1861

Open
jacalata wants to merge 1 commit into
developmentfrom
jac/subscription-refresh-extract-triggered
Open

Expose refreshExtractTriggered on SubscriptionItem#1861
jacalata wants to merge 1 commit into
developmentfrom
jac/subscription-refresh-extract-triggered

Conversation

@jacalata

Copy link
Copy Markdown
Contributor

Summary

Adds support for the REST API's refreshExtractTriggered="true" attribute on subscriptions -- the wire form of Tableau Cloud's "On Extract Refresh" subscriptions. When True, the subscription fires when the referenced schedule's extract refresh completes, rather than on the schedule's time trigger.

Closes #1658.

What changes

  • New SubscriptionItem.on_extract_refresh(subject, extract_refresh_schedule_id, user_id, target) classmethod factory -- the recommended way to construct these subscriptions.
  • refresh_extract_triggered is now a boolean property on SubscriptionItem. Its docstring covers the two ways the server can surprise callers:
    • Setting True with a non-extract-refresh schedule id is a server-side error.
    • Updates that change schedule_id cause the server to silently clear the flag to False on that same call; converting an existing time-based subscription requires two updates.
  • Subscriptions.create() and .update() now raise ValueError up front if schedule_id is missing, so what used to be a confusing wire-layer error becomes an actionable client-side message.
  • create_req emits refreshExtractTriggered="true" only when set. update_req emits both "true" and "false" unconditionally, so callers can turn the flag off on an existing subscription (the server retains the prior value when the attribute is absent).
  • _parse_element reads the attribute back into the property.

Compatibility note

Every subscriptions.update() payload now carries refreshExtractTriggered="true|false". Older servers that don't know the attribute should ignore unknown attrs on the <subscription> element per the schema's <xs:anyAttribute processContents="skip"/>; the attribute has been on the server since long before TSC's current minimum version.

Test plan

  • pytest test/test_subscription.py -q -- 16 pass, including 12 new tests covering the factory, defaults, create_req emit-when-set / omit-when-false, update_req always-emits in both directions, parse round-trip with and without the attribute, parse of inline-schedule responses (no schedule_id), and create()/update() rejection of missing schedule_id.
  • Full test suite -- 879 pass, 1 pre-existing skip.
  • Manual verification on a Tableau Cloud site: create a subscription via on_extract_refresh(), confirm it appears as "On Extract Refresh" in the web UI, and confirm it fires when the referenced extract refresh runs.

🤖 Generated with Claude Code

The Tableau REST API supports a `refreshExtractTriggered="true"` attribute
on subscription payloads that makes the subscription fire when its referenced
schedule's extract refresh completes, rather than on the schedule's time
trigger. On Tableau Cloud, this is the wire form of an "On Extract Refresh"
subscription. TSC never exposed this attribute; users trying to create these
subscriptions were passing `schedule_id=None` and hitting a confusing wire
error deep in the endpoint layer.

Changes:
- `SubscriptionItem.on_extract_refresh(...)` classmethod factory constructs
  a subscription with an extract-refresh schedule id and the flag set.
- `refresh_extract_triggered` exposed as a property with a docstring
  covering the two ways the server surprises callers (server rejects True
  with a non-extract schedule; server silently clears the flag when a
  schedule change is included in an update).
- `Subscriptions.create()` and `.update()` now raise `ValueError` up front
  when `schedule_id` is missing, so the wire error becomes an actionable
  client-side message.
- `create_req` emits `refreshExtractTriggered="true"` only when set;
  `update_req` emits both true and false so callers can turn the flag off
  on an existing subscription.
- `_parse_element` reads the attribute back into the property; parse
  continues to accept inline-schedule responses (schedule_id=None).

Tests cover: factory sets flag + schedule id; default false; create_req
emit-when-set/omit-when-false; update_req always emits; parse round-trip
for both true and missing; parse of inline-schedule responses; create()
and update() reject missing schedule_id.

Related to #1658.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Coverage

Coverage Report
FileStmtsMissCoverMissing
tableauserverclient
   __init__.py50100% 
   config.py150100% 
   datetime_helpers.py2511 96%
   exponential_backoff.py200100% 
   filesys_helpers.py310100% 
   namespace.py2633 88%
tableauserverclient/bin
   __init__.py20100% 
   _version.py358212212 41%
tableauserverclient/helpers
   __init__.py10100% 
   logging.py20100% 
   strings.py3111 97%
tableauserverclient/models
   __init__.py460100% 
   collection_item.py4177 83%
   column_item.py553232 42%
   connection_credentials.py351111 69%
   connection_item.py941414 85%
   custom_view_item.py1442121 85%
   data_acceleration_report_item.py5411 98%
   data_alert_item.py15844 97%
   data_freshness_policy_item.py1551515 90%
   database_item.py2073636 83%
   datasource_item.py3001212 96%
   dqw_item.py10455 95%
   exceptions.py40100% 
   extensions_item.py13244 97%
   extract_item.py4444 91%
   favorites_item.py6988 88%
   fileupload_item.py190100% 
   flow_item.py1491010 93%
   flow_run_item.py710100% 
   group_item.py8966 93%
   groupset_item.py4977 86%
   interval_item.py1823232 82%
   job_item.py1921010 95%
   linked_tasks_item.py7911 99%
   location_item.py2922 93%
   metric_item.py1291313 90%
   oidc_item.py6333 95%
   pagination_item.py3411 97%
   permissions_item.py1111212 89%
   project_item.py2073131 85%
   property_decorators.py1001818 82%
   reference_item.py2622 92%
   revision_item.py5911 98%
   schedule_item.py20966 97%
   server_info_item.py3777 81%
   site_item.py6361313 98%
   subscription_item.py11611 99%
   table_item.py1191818 85%
   tableau_auth.py612525 59%
   tableau_types.py2711 96%
   tag_item.py150100% 
   target.py60100% 
   task_item.py5622 96%
   user_item.py3101818 94%
   view_item.py2201616 93%
   virtual_connection_item.py6488 88%
   webhook_item.py6911 99%
   workbook_item.py3621616 96%
tableauserverclient/server
   __init__.py90100% 
   exceptions.py40100% 
   filter.py2911 97%
   pager.py3311 97%
   query.py1431515 90%
   request_factory.py1338177177 87%
   request_options.py38655 99%
   server.py1882323 88%
   sort.py60100% 
tableauserverclient/server/endpoint
   __init__.py350100% 
   auth_endpoint.py771111 86%
   custom_views_endpoint.py1521212 92%
   data_acceleration_report_endpoint.py210100% 
   data_alert_endpoint.py942323 76%
   databases_endpoint.py1113030 73%
   datasources_endpoint.py3233333 90%
   default_permissions_endpoint.py4433 93%
   dqw_endpoint.py451616 64%
   endpoint.py2122020 91%
   exceptions.py7766 92%
   extensions_endpoint.py310100% 
   favorites_endpoint.py942222 77%
   fileuploads_endpoint.py510100% 
   flow_runs_endpoint.py6299 85%
   flow_task_endpoint.py2122 90%
   flows_endpoint.py1985353 73%
   groups_endpoint.py12699 93%
   groupsets_endpoint.py7277 90%
   jobs_endpoint.py6799 87%
   linked_tasks_endpoint.py370100% 
   metadata_endpoint.py881414 84%
   metrics_endpoint.py5566 89%
   oidc_endpoint.py4211 98%
   permissions_endpoint.py4433 93%
   projects_endpoint.py1782424 87%
   resource_tagger.py1273535 72%
   schedules_endpoint.py1191111 91%
   server_info_endpoint.py361010 72%
   sites_endpoint.py1302727 79%
   subscriptions_endpoint.py601313 78%
   tables_endpoint.py1103636 67%
   tasks_endpoint.py6366 90%
   users_endpoint.py18388 96%
   views_endpoint.py15099 94%
   virtual_connections_endpoint.py1131010 91%
   webhooks_endpoint.py5499 83%
   workbooks_endpoint.py3382222 93%
TOTAL12029140388% 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unabled to create Subscriptions with schedule as "On Extract Refresh"

1 participant