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";
import Keywords from "@/components/Keywords";

# Running Tasks

Once you've [defined some tasks](/v1/tasks) and registered them on a [worker](/v1/workers), you're ready to run them!

Hatchet lets you run tasks in a number of ways, which support different application needs. In broad strokes, these are [fire-and-wait](#fire-and-wait), various forms of [fire-and-forget-style triggering](#fire-and-forget), and scheduling tasks to run either [periodically](#crons) or at some [specific time in the future](#scheduled-runs).

## Fire-and-wait

Fire-and-wait is a common way of triggering a task which blocks until it completes and returns a result. This is particularly useful for situations where you want to do something with the result of your task. For instance, if your task generates some LLM output which you want to return to the user or persist in the database, you might trigger a task, wait for it to complete, collect its result, and then continue on with your application logic.

<UniversalTabs items={["Python", "Typescript", "Go", "Ruby"]}>
  <Tabs.Tab title="Python">

Call `run` or `aio_run` on a `Task` or `Workflow` object to invoke it. These methods block until the task or workflow completes and return the result.

<Snippet src={snippets.python.child.trigger.running_a_task} />

The run methods in Hatchet's Python SDK also have async flavors you can `await`. These are prefixed with `aio_`, such as `aio_run`.

<Snippet src={snippets.python.child.trigger.running_a_task_aio} />

Note that the type of `input` here is a Pydantic model that matches the input schema of the task or workflow being triggered.

  </Tabs.Tab>
  <Tabs.Tab title="Typescript">

Call `run` on the `Task` object to invoke it. This returns a promise that resolves when the task completes and returns the result.

<Snippet src={snippets.typescript.simple.run.running_a_task} />

  </Tabs.Tab>
  <Tabs.Tab title="Go">

Call `Run` on the `Task` object to invoke it. This blocks until the task completes and returns the result.

<Snippet src={snippets.go.simple.main.running_a_task} />

  </Tabs.Tab>
  <Tabs.Tab title="Ruby">

Call `run` on the `Task` object to invoke it. This blocks until the task completes and returns the result.

    <Snippet src={snippets.ruby.child.trigger.running_a_task} />

  </Tabs.Tab>
</UniversalTabs>

## Fire-and-forget

On the other hand, fire-and-forget-style triggering enqueues a task without waiting for the result. This is useful for background jobs like sending emails, processing uploads, or kicking off long-running pipelines where the application does _not_ need to wait for the result to continue along.

<UniversalTabs items={["Python", "Typescript", "Go", "Ruby"]}>
  <Tabs.Tab title="Python">

Call `run_no_wait` on a `Task` or `Workflow` object to enqueue it fire-and-forget. This returns a `WorkflowRunRef` you can use to access the run ID and result later.

<Snippet src={snippets.python.trigger_methods.workflow.sync} />

There's also an async flavor:

<Snippet src={snippets.python.trigger_methods.workflow.async} />

Note that the type of `input` here is a Pydantic model that matches the input schema of the task.

  </Tabs.Tab>
  <Tabs.Tab title="Typescript">

Call `run_no_wait` on the `Task` object to enqueue it without waiting for the result. This returns a `WorkflowRunRef`.

  </Tabs.Tab>
  <Tabs.Tab title="Go">

Call `RunNoWait` on the `Task` object to enqueue it without waiting for the result. This returns a `WorkflowRunRef`.

<Snippet src={snippets.go.simple.main.running_a_task_without_waiting} />

  </Tabs.Tab>
  <Tabs.Tab title="Ruby">

Call `run_no_wait` on the `Task` object to enqueue it without waiting for the result. This returns a `WorkflowRunRef`.

    <Snippet src={snippets.ruby.trigger_methods.workflow.sync} />

  </Tabs.Tab>
</UniversalTabs>

When running a task fire-and-forget-style, you can also always retrieve the result later on. The workflow run ref that's returned from these trigger methods has a result method, which lets you retrieve the result of the triggered task if you need it later.

<UniversalTabs items={["Python", "Typescript", "Go", "Ruby"]} variant="hidden">
  <Tabs.Tab title="Python">

Use `ref.result()` to block until the result is available:

<Snippet src={snippets.python.trigger_methods.workflow.result_sync} />

or await `aio_result`:

<Snippet src={snippets.python.trigger_methods.workflow.result_async} />

  </Tabs.Tab>
  <Tabs.Tab title="Typescript">
    <Snippet src={snippets.typescript.simple.enqueue.subscribing_to_results} />
  </Tabs.Tab>
  <Tabs.Tab title="Go">
    <Snippet src={snippets.go.simple.main.subscribing_to_results} />
  </Tabs.Tab>
  <Tabs.Tab title="Ruby">
    <Snippet src={snippets.ruby.trigger_methods.workflow.result_sync} />
  </Tabs.Tab>
</UniversalTabs>

### Triggering from events

Another method of running tasks fire-and-forget style is via [pushing events](/v1/events#pushing-events-to-hatchet) to Hatchet. If a task is configured to be triggered by an event, then when the event is pushed to Hatchet, a corresponding run will be triggered using the payload of the event as the input to the run.

You can push events to Hatchet directly using the SDKs, or via [webhooks](/v1/webhooks), which are converted into Hatchet events internally on ingestion.

## Crons

Another common way to run tasks is on a cron schedule, which Hatchet [supports natively](/v1/cron-runs). Crons are useful for running tasks that are expected to run at the same time every day, such as data processing pipelines, reconciliation jobs, and so on.

Note that Hatchet supports second-level cron granularity, although in most cases using the minutes as the most granular level is perfectly fine.

## Scheduled runs

Finally, Hatchet also supports [scheduling a run to be triggered at a specific time in the future](/v1/scheduled-runs). This is particularly useful for situations where you want to wait a known amount of time before running some task, such as sending a follow up email or a welcome email to a new user, or allowing your customers to choose when they want something to run, such as sending a reminder, for instance.

## Triggering from the dashboard

Finally, there are a number of pages in the dashboard that have a `Trigger Run` button. You can provide run parameters such as input, additional metadata, and a scheduled time.

![Create Scheduled Run](../../public/schedule-dash.gif)

<Keywords keywords="trigger, enqueue, fire-and-forget, fire-and-wait, run, event, webhook, cron, schedule" />
