Skip to content

Commit 5ea2818

Browse files
authored
Improve long-running operations (#58)
## Changes - Adds `callback` optional argument to every waiter. - Adds typed response where applicable to `Wait` instances. - Exposes `.bind()` on `Wait` for cross-process-boundary waiting. - `examples/starting_job_and_waiting.py` for a detailed demonstration. ## Tests - [x] `make test` run locally - [x] `make fmt` applied - [x] relevant integration tests applied
1 parent 6d56869 commit 5ea2818

File tree

13 files changed

+352
-55
lines changed

13 files changed

+352
-55
lines changed

.codegen/service.py.tmpl

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from dataclasses import dataclass
44
from datetime import timedelta
55
from enum import Enum
6-
from typing import Dict, List, Any, Iterator, Type
6+
from typing import Dict, List, Any, Iterator, Type, Callable
77
import time
88
import random
99
import logging
@@ -52,7 +52,7 @@ class {{.PascalName}}{{if eq "List" .PascalName}}Request{{end}}:{{if .Descriptio
5252
{{- define "as_request_type" -}}
5353
{{- if not .Entity }}None # ERROR: No Type
5454
{{- else if .Entity.ArrayValue }}[{{if .Entity.ArrayValue.IsObject}}v.as_dict(){{else}}v{{end}} for v in self.{{.SnakeName}}]
55-
{{- else if .Entity.IsObject }}self.{{.SnakeName}}.as_dict()
55+
{{- else if or .Entity.IsObject .Entity.IsExternal }}self.{{.SnakeName}}.as_dict()
5656
{{- else if .Entity.Enum }}self.{{.SnakeName}}.value
5757
{{- else}}self.{{.SnakeName}}{{- end -}}
5858
{{- end -}}
@@ -89,7 +89,8 @@ class {{.Name}}API:{{if .Description}}
8989
def __init__(self, api_client):
9090
self._api = api_client
9191
{{range .Waits}}
92-
def {{.SnakeName}}(self{{range .Binding}}, {{.PollField.SnakeName}}: {{template "type-nq" .PollField.Entity}}{{end}}, timeout=timedelta(minutes={{.Timeout}})) -> {{.Poll.Response.PascalName}}:
92+
def {{.SnakeName}}(self{{range .Binding}}, {{.PollField.SnakeName}}: {{template "type-nq" .PollField.Entity}}{{end}},
93+
timeout=timedelta(minutes={{.Timeout}}), callback: Callable[[{{.Poll.Response.PascalName}}], None] = None) -> {{.Poll.Response.PascalName}}:
9394
deadline = time.time() + timeout.total_seconds()
9495
target_states = ({{range .Success}}{{.Entity.PascalName}}.{{.Content}}, {{end}}){{if .Failure}}
9596
failure_states = ({{range .Failure}}{{.Entity.PascalName}}.{{.Content}}, {{end}}){{end}}
@@ -109,6 +110,8 @@ class {{.Name}}API:{{if .Description}}
109110
{{- end}}
110111
if status in target_states:
111112
return poll
113+
if callback:
114+
callback(poll)
112115
{{if .Failure -}}
113116
if status in failure_states:
114117
msg = f'failed to reach {{range $i, $e := .Success}}{{if $i}} or {{end}}{{$e.Content}}{{end}}, got {status}: {status_message}'
@@ -166,8 +169,9 @@ class {{.Name}}API:{{if .Description}}
166169

167170
{{define "method-call-retried" -}}
168171
{{if .Response}}op_response = {{end}}{{template "method-do" .}}
169-
return Wait(self.{{.Wait.SnakeName}}, {{range $i, $b := .Wait.Binding}}{{if $i}}, {{end}}
170-
{{.PollField.SnakeName}}={{if .IsResponseBind}}op_response['{{.Bind.Name}}']{{else}}request.{{.Bind.SnakeName}}{{end}}
172+
return Wait(self.{{.Wait.SnakeName}}
173+
{{if .Response}}, response = {{.Response.PascalName}}.from_dict(op_response){{end}}
174+
{{range .Wait.Binding}}, {{.PollField.SnakeName}}={{if .IsResponseBind}}op_response['{{.Bind.Name}}']{{else}}request.{{.Bind.SnakeName}}{{end}}
171175
{{- end}})
172176
{{- end}}
173177

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@ info = w.clusters.create_and_wait(cluster_name='Created cluster',
220220
logging.info(f'Created: {info}')
221221
```
222222

223+
Please look at the `examples/starting_job_and_waiting.py` for a more advanced usage.
224+
223225
## Paginated responses
224226

225227
On the platform side the Databricks APIs have different wait to deal with pagination:
@@ -240,6 +242,8 @@ for repo in w.repos.list():
240242
logging.info(f'Found repo: {repo.path}')
241243
```
242244

245+
Please look at the `examples/last_job_runs.py` for a more advanced usage.
246+
243247
## Single-Sign-On (SSO) with OAuth
244248

245249
### Authorization Code flow with PKCE

databricks/sdk/service/_internal.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,20 @@ def _enum(d: Dict[str, any], field: str, cls: Type) -> any:
2626

2727
class Wait(Generic[ReturnType]):
2828

29-
def __init__(self, waiter: Callable, **kwargs) -> None:
29+
def __init__(self, waiter: Callable, response: any = None, **kwargs) -> None:
30+
self.response = response
31+
3032
self._waiter = waiter
31-
self.arguments = kwargs
33+
self._bind = kwargs
34+
35+
def __getattr__(self, key) -> any:
36+
return self._bind[key]
37+
38+
def bind(self) -> dict:
39+
return self._bind
3240

33-
def result(self, timeout: datetime.timedelta = None) -> ReturnType:
34-
kwargs = self.arguments.copy()
35-
if timeout:
36-
kwargs['timeout'] = timeout
37-
return self._waiter(**kwargs)
41+
def result(self,
42+
timeout: datetime.timedelta = None,
43+
callback: Callable[[ReturnType], None] = None) -> ReturnType:
44+
kwargs = self._bind.copy()
45+
return self._waiter(callback=callback, timeout=timeout, **kwargs)

databricks/sdk/service/clusters.py

Lines changed: 16 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

databricks/sdk/service/commands.py

Lines changed: 26 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

databricks/sdk/service/deployment.py

Lines changed: 10 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

databricks/sdk/service/endpoints.py

Lines changed: 13 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)