Skip to content

Commit 01d648c

Browse files
authored
add exit hook docs (#151)
1 parent 0cafd16 commit 01d648c

File tree

4 files changed

+67
-3
lines changed

4 files changed

+67
-3
lines changed

docs/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ Metaflow makes it easy to build and manage real-life data science, AI, and ML pr
4040

4141
- [Introduction to Scalable Compute and Data](scaling/introduction)
4242
- [Computing at Scale](scaling/remote-tasks/introduction)
43-
- [Managing Dependencies](scaling/dependencies)*New support for `uv`*
44-
- [Dealing with Failures](scaling/failures)
43+
- [Managing Dependencies](scaling/dependencies)*New: support for `uv`*
44+
- [Dealing with Failures](scaling/failures)*New: support for `@exit_hook`*
4545
- [Checkpointing Progress](scaling/checkpoint/introduction)*New*
4646
- [Loading and Storing Data](scaling/data)
4747
- [Organizing Results](scaling/tagging)

docs/metaflow/composing-flows/introduction.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ steps and flows. For example, you might define shared, project-specific patterns
1313
- Tracking data and model lineage,
1414
- Performing feature engineering and transformations,
1515
- Training and evaluating a model,
16-
- Accessing an external service, e.g. an LLM endpoint through a model router.
16+
- Accessing an external service, e.g. an LLM endpoint through a model router,
17+
- Making tools available for agentic workflows.
1718

1819
You can handle cases like these by developing a shared library that encapsulates
1920
the logic and importing it in your steps. Metaflow will [package the

docs/production/scheduling-metaflow-flows/scheduling-with-argo-workflows.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,14 @@ production.
308308

309309
On Argo Workflows we support sending notifications on a successful or failed flow. To enable notifications, supply the `--notify-on-success/--notify-on-error` flags while deploying your flow. You must also configure the notification provider. The ones currently supported are
310310

311+
### Custom notifications
312+
313+
:::info
314+
New in Metaflow 2.16
315+
:::
316+
317+
You can set up a custom function to be called on success or failure on Argo Workflows using [exit hooks](/scaling/failures#exit-hooks-executing-a-function-upon-success-or-failure).
318+
311319
### Slack notifications
312320

313321
In order to enable Slack notifications, we need to first create a webhook endpoing that Metaflow can send the notifications to by following the instructions at https://api.slack.com/messaging/webhooks

docs/scaling/failures.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,60 @@ if __name__ == '__main__':
329329

330330
This example handles a timeout in `start` gracefully without showing any exceptions.
331331

332+
## Exit hooks: Executing a function upon success or failure
333+
334+
:::info
335+
This is a new feature in Metaflow 2.16. Exit hooks work with local runs and when
336+
[deployed on Argo Workflows](/production/scheduling-metaflow-flows/scheduling-with-argo-workflows).
337+
:::
338+
339+
Exit hooks let you define a special function that runs at the end of a flow, regardless
340+
of whether the flow succeeds or fails. Unlike the end step, which is skipped if the flow
341+
fails, exit hooks always run. This makes them suitable for tasks like sending notifications
342+
or cleaning up resources. However, since they run outside of steps, they cannot be used to
343+
produce artifacts.
344+
345+
You can attach one or more exit hook functions to a flow using the `@exit_hook` decorator. For example:
346+
347+
```python
348+
from metaflow import step, FlowSpec, Parameter, exit_hook, Run
349+
350+
def success_print():
351+
print("✅ Flow completed successfully!")
352+
353+
def failure_print(run):
354+
if run:
355+
print(f"💥 Run {run.pathspec} failed. Failed tasks:")
356+
for step in run:
357+
for task in step:
358+
if not task.successful:
359+
print(f"{task.pathspec}")
360+
else:
361+
print(f"💥 Run failed during initialization")
362+
363+
@exit_hook(on_error=[failure_print], on_success=[success_print])
364+
class ExitHookFlow(FlowSpec):
365+
should_fail = Parameter(name="should-fail", default=False)
366+
367+
@step
368+
def start(self):
369+
print("Starting 👋")
370+
print("Should fail?", self.should_fail)
371+
if self.should_fail:
372+
raise Exception("failing as expected")
373+
self.next(self.end)
374+
375+
@step
376+
def end(self):
377+
print("Done! 🏁")
378+
379+
if __name__ == "__main__":
380+
ExitHookFlow()
381+
```
382+
383+
Note that when deployed on Argo Workflows, exit hook functions execute as separate
384+
containers (pods), so they will execute even if steps fail e.g. due to out of memory condition.
385+
332386
## Summary
333387

334388
Here is a quick summary of failure handling in Metaflow:
@@ -341,4 +395,5 @@ Here is a quick summary of failure handling in Metaflow:
341395
safely](failures.md#how-to-prevent-retries). It is a good idea to use `times=0` for
342396
`retry` in this case.
343397
* Use `timeout` with any of the above if your code can get stuck.
398+
* Use `@exit_hook` to execute custom functions upon success or failure.
344399

0 commit comments

Comments
 (0)