Polling Async Tasks

Some operations on Stream's API take longer than a single HTTP response can wait for. Hard-delete-channels, channel export, user export, and similar batch jobs return a task_id immediately and run in the background. To get the result, poll the task status endpoint.

The SDK ships a helper that polls for you and surfaces the outcome as either a typed result (when the task completes) or a typed exception (when it fails or the wait elapses).

Waiting on a task

import (
    "context"
    "errors"
    "github.com/GetStream/getstream-go/v4"
)

resp, err := client.Chat().DeleteChannels(ctx, &getstream.DeleteChannelsRequest{
    Cids:       []string{"messaging:c1", "messaging:c2"},
    HardDelete: getstream.PtrTo(true),
})
if err != nil {
    return err
}

taskResp, err := getstream.WaitForTask(ctx, client, *resp.Data.TaskID)
if err != nil {
    var streamErr *getstream.StreamError
    if errors.As(err, &streamErr) {
        if errors.Is(err, getstream.ErrTaskFailed) {
            // task ended with status: failed; streamErr.Task carries the details
        } else if errors.Is(err, getstream.ErrTransport) && streamErr.ErrorType == "timeout" {
            // wait elapsed; task may still be running on the server
        }
    }
}

Behavior

Task outcomeHelper's reaction
status: "completed"Returns the task result payload.
status: "failed"Raises the SDK's task exception with task_id, error_type, description, stack_trace, version.
Deadline exceededRaises the SDK's transport exception with error_type = "timeout". The task may still be running on the server.

Java exposes the server-side stack trace via getStackTraceText(), not getStackTrace(). The latter is reserved for the JVM's own Throwable.getStackTrace() (StackTraceElement[]).

Defaults

ParameterDefault
Poll interval1 second
Wait timeout60 seconds

Override either knob if your task is expected to run longer, or if you want a tighter loop.

import "time"

getstream.WaitForTask(ctx, client, taskID,
    getstream.WithWaitForTaskPollInterval(5*time.Second),
    getstream.WithWaitForTaskTimeout(10*time.Minute),
)

Polling manually

If you need a custom polling loop (back-off, progress logging, external cancellation), call getTask yourself. The helper is a convenience over the same endpoint.

for {
    resp, err := client.GetTask(ctx, taskID, &getstream.GetTaskRequest{})
    if err != nil { return err }
    if resp.Data.Status == "completed" || resp.Data.Status == "failed" {
        break
    }
    time.Sleep(time.Second)
}

The Async variant in your SDK (e.g. Python's AsyncStream.wait_for_task, .NET's WaitForTaskAsync) is non-blocking and accepts the same parameters.