import { snippets } from "@/lib/generated/snippets";
import { Snippet } from "@/components/code";
import { Callout, Card, Cards, Steps, Tabs } from "nextra/components";
import UniversalTabs from "@/components/UniversalTabs";

# Lifespans

<Callout type="error" emoji="🚨">
  Lifespans are an **experimental feature** in Hatchet, and are subject to
  change.
</Callout>

Hatchet's Python SDK allows you define a **_lifespan_**, which is an async generator that runs when your worker starts up and cleans up when it exits, which lets you share state across all of the tasks running on the worker. This behaves almost identically to [FastAPI's lifespans](https://fastapi.tiangolo.com/advanced/events/), and is intended to be used in the same way. Lifespans are useful for sharing state like connection pools across all tasks on a single worker. They also work great for loading expensive machine learning models into memory before the worker starts.

<Callout type="warning" emoji="⚠️">
  We recommend only using lifespans for storing **_immutable_** state to share
  between tasks running on your worker. The intention is not to e.g. store a
  counter of the number of tasks that a worker has run and increment that
  counter on each task run. This is prone to unexpected behavior due to
  concurrency in Hatchet.
</Callout>

## Usage

To use Hatchet's `lifespan` feature, define an async generator and pass it into your `worker`:

<Snippet src={snippets.python.lifespans.worker.define_a_lifespan} />

When the worker starts, it will run the lifespan up to the `yield`. Then, on worker shutdown, it will clean up by running everything after the `yield` (the same as with any other generator).

<Callout type="warning" emoji="⚠️">
  Your lifespan must only `yield` **_once_**.
</Callout>

Then, to use your lifespan in a task, you can extract it from the context with `Context.lifespan`.

<Snippet src={snippets.python.lifespans.worker.use_the_lifespan_in_a_task} />

<Callout type="info" emoji="💡">
  For type checking, cast the `Context.lifespan` to whatever type your lifespan
  generator yields.
</Callout>

And that's it! Now, any task running on the worker with the lifespan provided will have access to the lifespan data.
