Skip to content

Conversation

@vogelsgesang
Copy link
Collaborator

Based on @FrancoisZim 's suggestion.
Currently still a draft to get feedback on the proposed interface. Will add test cases, as soon as we got agreement on the interface & functionality.

This commit adds a wait_for_job method which will repeatedly poll
a job's status until that job is finished.

Internally, it uses an exponential backoff for the polling intervals.
That way, it is snappy for fast-running jobs without putting too
much load on the server for long-running jobs.

It returns the successfully finished JobItem object which might be
of interest to the caller, e.g. to inspect the reported started_at
finished_at times or the notes.

For failed jobs, wait_for_job raises an exception. That way, we
ensure that errors in jobs don't accidentally go unnoticed. The
jobs object can still be retrieved from the exception object, if
required.

@t8y8
Copy link
Collaborator

t8y8 commented Sep 24, 2021

It makes sense to me.

The back of my head is asking if the Jobs endpoint is the right place for logic like that -- I think this would be the first 'utility' method we have on an endpoint... Is there a different way to present it like a TSC.Waiter that can handle other wait-retry-backoff methods?

Maybe that's too much, it's a bit off-the-cuff. Let me know what you think, otherwise I'll give this code as is a deeper review

@FrancoisZim
Copy link

Looks good to me. I don't really agree with @t8y8 about a generalizable TSC.Waiter class - I think all async operations spawn a background job and so this is the right place to implement this wait logic.

@vogelsgesang
Copy link
Collaborator Author

I think this would be the first 'utility' method we have on an endpoint...

server.filesuploads.upload is also kind of an utility method. It chunks the file into multiple parts and uploads each chunk through a separate HTTP request. Similarly most publish methods (workbooks, datasources, ...) encapsulate multiple API calls into one utility method (first the upload, then the actual publish)

But I see what you mean here... To me the main question would be:

Is there a different way to present it like a TSC.Waiter that can handle other wait-retry-backoff methods?

which makes me wonder: which other things would there in the Tableau Server API which we might want to wait on?
If there are other things we want to wait on than jobs: yes, maybe a TSC.Waiter makes sense...

But afaict the "jobs" concept is already Tableau's abstraction for everything async on the server, and hence introducing another layer of abstraction on the client would add only limited value

Copy link
Collaborator

@t8y8 t8y8 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor changes.

I also want to verify this works for AD sync, and I think it does (

def create_AD_group(self, group_item, asJob=False):
) -- but confirm that should be poll-able as well

@jacalata
Copy link
Contributor

The other thing we can wait for is a Flow Run, which might actually be what the BackgroundJobItem is related to now I look some more. @jorwoods how does this look to you in the context of adding the flows endpoints?

@jorwoods
Copy link
Contributor

Regarding any changes to #884, this would not be too difficult to implement on the flow_runs endpoint as well.

@vogelsgesang
Copy link
Collaborator Author

argh... Ok, so flows are also de-facto jobs, but for some reason didn't use the jobs API. That's sad 😢 Such a nice abstraction on the server side, but then its inconistent by one job type not using the common REST interface... @jacalata maybe the "jobs" endpoint/abstraction should be added as a guideline to the TAG design guidelines for our REST API?

Either way, it is what it is... I will rewrite this code to pull out the "retry with exponential backoff" logic, such that it can be reused across multiple places, in particular also by @jorwoods in the flow endpoint, without having to duplicate that logic.
Will only have time for this a few days from now, though

@vogelsgesang vogelsgesang force-pushed the wait-for-job branch 2 times, most recently from a44c63d to 4eee552 Compare October 5, 2021 19:01
@vogelsgesang vogelsgesang marked this pull request as ready for review October 5, 2021 19:02
@vogelsgesang
Copy link
Collaborator Author

added test cases and refactored the waiting logic into a reusable ExponentialBackoffTimer which can also be reused for flows.

I think this should be ready for the final review now

This commit adds a `wait_for_job` method which will repeatedly poll
a job's status until that job is finished.

Internally, it uses an exponential backoff for the polling intervals.
That way, it is snappy for fast-running jobs without putting too
much load on the server for long-running jobs.

It returns the successfully finished `JobItem` object which might be
of interest to the caller, e.g. to inspect the reported `started_at`
`finished_at` times or the `notes`.

For failed jobs, `wait_for_job` raises an exception. That way, we
ensure that errors in jobs don't accidentally go unnoticed. The
`jobs` object can still be retrieved from the exception object, if
required.
Copy link
Collaborator

@t8y8 t8y8 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great -- thanks for doing the diligence and discovering flows don't fit the pattern. (I'm not too surprised they don't, there was significant time between BG Jobs and Flows Runs).

The testing of the BackoffTimer is excellent -- I'm excited that a bonus of this implementation is that anyone can use the timer to write their own backoff between retries of non job calls, like waiting for SOLR to update or something.

🚀

@vogelsgesang vogelsgesang merged commit 9ccc713 into tableau:development Oct 6, 2021
vogelsgesang added a commit to vogelsgesang/server-client-python that referenced this pull request Oct 6, 2021
This commit adds the corresponding documentation for PR tableau#903
@vogelsgesang vogelsgesang deleted the wait-for-job branch October 6, 2021 23:24
vogelsgesang added a commit that referenced this pull request Oct 7, 2021
Should have been part of #903, but I forgot to `git add` them :/
vogelsgesang added a commit that referenced this pull request Oct 21, 2021
This commit adds the corresponding documentation for PR #903
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.

5 participants