> ## Documentation Index
> Fetch the complete documentation index at: https://ziva.zeleza.ru/llms.txt
> Use this file to discover all available pages before exploring further.

# Advanced Queue Playbook

> Conditional flows, dynamic task generation, and resilient retries

# Advanced Queue Playbook

These examples illustrate how to orchestrate non-trivial workflows with Ziva:

* split a process into multiple stages and append tasks dynamically;
* react to user choices and task outcomes;
* recover from errors without leaving the TUI.

<Info>
  All snippets rely on the public `ziva` API. Keep them in an `examples` package and call the helpers when you need to demonstrate behaviour.
</Info>

## Multi-stage deployment template

```go theme={null}
// DeployCluster orchestrates a sequential setup that gathers user input,
// displays progress, and stores intermediate results for later stages.
func DeployCluster() error {
    summary := ziva.NewFuncTask(
        "Preflight checks",
        runPreflightChecks,
        ziva.WithSummaryFunction(func() []string {
            return []string{"DNS: ok", "Network: ok"}
        }),
        ziva.WithStopOnError(true),
    )

    topology := ziva.NewSingleSelectTask(
        "Topology",
        []string{
            "single-node::Single node",
            "multi-node::Multi node",
            "ha::High availability",
        },
    ).WithDefaultItem("multi-node")

    nodes := ziva.NewInputTask(
        "Node count",
        "How many worker nodes do we provision?",
    ).
        WithInputType(ziva.InputTypeNumber).
        WithValidator(ziva.DefaultValidators.Range(1, 20)).
        WithTimeout(30*time.Second, "3")

    queue := ziva.NewQueue("Ziva Deployment").
        WithAppName("Ziva CLI").
        WithTasksNumbered(true, "[%02d]")

    queue.AddTasks(summary, topology, nodes)
    if err := queue.Run(); err != nil {
        return err
    }

    // Add context-aware tasks based on the selected topology.
    followUp := ziva.NewQueue("Follow-up tasks")

    switch topology.GetSelected() {
    case "single-node":
        followUp.AddTasks(planBackupTask(), confirmMetricsTask())
    case "multi-node":
        followUp.AddTasks(configureIngressTask(), scaleOutTask(nodes))
    case "ha":
        followUp.AddTasks(haPrecheckTask(), configureQuorumTask(nodes))
    }

    return followUp.Run()
}
```

### Highlights

* **Two queue runs.** The first queue captures input; the second queue is assembled at runtime.
* **Summary function.** `WithSummaryFunction` displays a concise recap under the task and improves operator feedback.
* **Timeouts.** `WithTimeout` prevents headless sessions from hanging indefinitely.

## Retrying with user confirmation

```go theme={null}
func RunWithRetries(label string, fn func() error, maxAttempts int) error {
    attempt := 1

    for {
        task := ziva.NewFuncTask(
            fmt.Sprintf("%s · attempt %d", label, attempt),
            fn,
            ziva.WithStopOnError(false),
        )

        queue := ziva.NewQueue(label)
        queue.AddTasks(task)

        if err := queue.Run(); err == nil {
            return nil
        }

        if attempt >= maxAttempts {
            return fmt.Errorf("reached max attempts (%d)", maxAttempts)
        }

        retry := ziva.NewYesNoTask(
            "Retry",
            fmt.Sprintf("Attempt %d failed. Retry?", attempt),
        ).WithDefaultYesAndTimeout(10 * time.Second)

        confirmation := ziva.NewQueue("Retry decision")
        confirmation.AddTasks(retry)
        confirmation.Run()

        if !retry.IsYes() {
            return fmt.Errorf("operation cancelled at attempt %d", attempt)
        }

        attempt++
    }
}
```

### When to use it

* flaky infrastructure calls;
* firmware updates over unstable connections;
* long-running operations that deserve a human-confirmed retry.

## Building tasks on the fly

```go theme={null}
func ConfigureServers() error {
    count := ziva.NewInputTask("Server count", "How many servers do we configure?").
        WithInputType(ziva.InputTypeNumber).
        WithValidator(ziva.DefaultValidators.Range(1, 8))

    baseQueue := ziva.NewQueue("Configuration parameters")
    baseQueue.AddTasks(count)
    if err := baseQueue.Run(); err != nil {
        return err
    }

    n, _ := strconv.Atoi(count.GetValue())

    var tasks []ziva.Task
    for i := 1; i <= n; i++ {
        prefix := fmt.Sprintf("Server %d", i)

        host := ziva.NewInputTask(prefix+" · host", "Enter FQDN")
        host.WithValidator(ziva.DefaultValidators.Domain())

        port := ziva.NewInputTask(prefix+" · port", "Enter port")
        port.WithInputType(ziva.InputTypeNumber).
            WithValidator(ziva.DefaultValidators.Port())

        tasks = append(tasks, host, port)
    }

    servers := ziva.NewQueue("Server configuration").
        WithTasksNumbered(true, "[%02d]")
    servers.AddTasks(tasks...)
    return servers.Run()
}
```

<Note>
  If a workflow can generate hundreds of tasks, split the execution into several queues and run them in batches to keep memory usage predictable.
</Note>

## Quick checklist for complex flows

* Keep references to tasks whose results you need later.
* Use separate queues for distinct stages — it simplifies reasoning and module tests.
* Call `AutoConfigure()` on startup so Ziva tunes itself for the target environment.
* Combine `EnableEmbeddedMode()` with `WithOutResultLine()` on constrained devices to keep the output compact.
* Remember that the queue is sequential; if you need pseudo-parallel work, launch extra queues from `FuncTask` handlers.

Continue with the validation demo to see how to compose robust forms.
