Skip to content

Commit 0f335b4

Browse files
committed
Continue sketching
1 parent 7064b7a commit 0f335b4

File tree

1 file changed

+47
-42
lines changed

1 file changed

+47
-42
lines changed

update/job_runner_I1_native.py

Lines changed: 47 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ class JobOutput:
4242
UpdateID = str
4343
Workflow = Type
4444

45+
46+
@dataclass
47+
class Update:
48+
id: UpdateID
49+
arg: I
50+
51+
4552
_sdk_internals_pending_tasks_count = 0
4653
_sdk_internals_handler_mutex = asyncio.Lock()
4754

@@ -54,11 +61,11 @@ def _sdk_internals_all_handlers_completed(self) -> bool:
5461

5562
@asynccontextmanager
5663
async def _sdk_internals__track_pending__wait_until_ready__serialize_execution(
57-
ready_condition: Callable[[], bool]
64+
execute_condition: Callable[[], bool]
5865
):
5966
global _sdk_internals_pending_tasks_count
6067
_sdk_internals_pending_tasks_count += 1
61-
await workflow.wait_condition(ready_condition)
68+
await workflow.wait_condition(execute_condition)
6269
await _sdk_internals_handler_mutex.acquire()
6370
try:
6471
yield
@@ -72,29 +79,30 @@ class SDKInternals:
7279
# pending tasks tracking, and synchronization functionality. This is a fake implementation: the
7380
# real implementation will automatically inspect and wrap the user's declared update handlers.
7481

75-
def ready_to_execute(self, arg: I) -> bool:
76-
# Implemented by user
82+
def ready_to_execute(self, update: Update) -> bool:
83+
# Overridden by users who wish to control order of execution
7784
return True
7885

7986
@workflow.update
8087
async def run_shell_script_job(self, arg: I) -> O:
8188
handler = getattr(self, "_" + inspect.currentframe().f_code.co_name)
8289
async with _sdk_internals__track_pending__wait_until_ready__serialize_execution(
83-
lambda: self.ready_to_execute(arg)
90+
lambda: self.ready_to_execute(Update(arg.id, arg))
8491
):
8592
return await handler(arg)
8693

8794
@workflow.update
8895
async def run_python_job(self, arg: I) -> O:
8996
handler = getattr(self, "_" + inspect.currentframe().f_code.co_name)
9097
async with _sdk_internals__track_pending__wait_until_ready__serialize_execution(
91-
lambda: self.ready_to_execute(arg)
98+
lambda: self.ready_to_execute(Update(arg.id, arg))
9299
):
93100
return await handler(arg)
94101

95102

96103
# Monkey-patch proposed new public API
97104
setattr(workflow, "all_handlers_completed", _sdk_internals_all_handlers_completed)
105+
setattr(workflow, "Update", Update)
98106
##
99107
## END SDK internals prototype
100108
##
@@ -115,12 +123,13 @@ async def run(self):
115123
await workflow.wait_condition(
116124
lambda: (
117125
workflow.info().is_continue_as_new_suggested()
118-
and self.all_handlers_completed()
126+
and workflow.all_handlers_completed()
119127
)
120128
)
121129
workflow.continue_as_new()
122130

123-
def ready_to_execute(self, job: Job) -> bool:
131+
def ready_to_execute(self, update: workflow.Update) -> bool:
132+
job = update.arg
124133
if not set(job.depends_on) <= self.completed_tasks:
125134
return False
126135
if after_time := job.after_time:
@@ -129,45 +138,41 @@ def ready_to_execute(self, job: Job) -> bool:
129138
return True
130139

131140
# These are the real handler functions. When we implement SDK support, these will use the
132-
# @workflow.update decorator and will not use an underscore prefix.
141+
# decorator form commented out below, and will not use an underscore prefix.
133142

134-
# @workflow.update
143+
# @workflow.update(execute_condition=ready_to_execute)
135144
async def _run_shell_script_job(self, job: Job) -> JobOutput:
136-
try:
137-
if security_errors := await workflow.execute_activity(
138-
run_shell_script_security_linter,
139-
args=[job.run],
140-
start_to_close_timeout=timedelta(seconds=10),
141-
):
142-
return JobOutput(status=1, stdout="", stderr=security_errors)
143-
job_output = await workflow.execute_activity(
144-
run_job, args=[job], start_to_close_timeout=timedelta(seconds=10)
145-
)
146-
return job_output
147-
finally:
148-
# FIXME: unbounded memory usage
149-
self.completed_tasks.add(job.id)
145+
if security_errors := await workflow.execute_activity(
146+
run_shell_script_security_linter,
147+
args=[job.run],
148+
start_to_close_timeout=timedelta(seconds=10),
149+
):
150+
return JobOutput(status=1, stdout="", stderr=security_errors)
151+
job_output = await workflow.execute_activity(
152+
run_job, args=[job], start_to_close_timeout=timedelta(seconds=10)
153+
)
154+
# FIXME: unbounded memory usage
155+
self.completed_tasks.add(job.id)
156+
return job_output
150157

151-
# @workflow.update
158+
# @workflow.update(execute_condition=ready_to_execute)
152159
async def _run_python_job(self, job: Job) -> JobOutput:
153-
try:
154-
if not await workflow.execute_activity(
155-
check_python_interpreter_version,
156-
args=[job.python_interpreter_version],
157-
start_to_close_timeout=timedelta(seconds=10),
158-
):
159-
return JobOutput(
160-
status=1,
161-
stdout="",
162-
stderr=f"Python interpreter version {job.python_interpreter_version} is not available",
163-
)
164-
job_output = await workflow.execute_activity(
165-
run_job, args=[job], start_to_close_timeout=timedelta(seconds=10)
160+
if not await workflow.execute_activity(
161+
check_python_interpreter_version,
162+
args=[job.python_interpreter_version],
163+
start_to_close_timeout=timedelta(seconds=10),
164+
):
165+
return JobOutput(
166+
status=1,
167+
stdout="",
168+
stderr=f"Python interpreter version {job.python_interpreter_version} is not available",
166169
)
167-
return job_output
168-
finally:
169-
# FIXME: unbounded memory usage
170-
self.completed_tasks.add(job.id)
170+
job_output = await workflow.execute_activity(
171+
run_job, args=[job], start_to_close_timeout=timedelta(seconds=10)
172+
)
173+
# FIXME: unbounded memory usage
174+
self.completed_tasks.add(job.id)
175+
return job_output
171176

172177

173178
@activity.defn

0 commit comments

Comments
 (0)