Go SDK

github.com/runnev/runnev-go — официальный Go-SDK. Только стандартная библиотека, без внешних модулей, Go 1.21+. Полностью учитывает context; подписки доставляют пакеты по каналу.

Установка

bash
go get github.com/runnev/runnev-go@v1.4.2

Настройка

go
import "github.com/runnev/runnev-go"

client := runnev.New(runnev.Options{
    APIKey:     os.Getenv("RUNNEV_API_KEY"), // обязательно
    BaseURL:    "https://runnev.dev/v1",      // по умолчанию
    Timeout:    30 * time.Second,             // на унарный запрос; не на поток подписки
    MaxRetries: 4,                            // повторы при 429 / 5xx
})

Публикация

go
ctx := context.Background()

stream, err := client.CreateStream(ctx, runnev.CreateStreamParams{
    Name: "orders-eu", RetentionSeconds: 86400,
})

// явный номер — идемпотентно, безопасно повторять
res, err := client.Publish(ctx, stream.ID, 41823, []runnev.Event{
    {"type": "order.paid", "id": "o_5521", "amount": 1999},
})
_ = res.Cursor // 41823

// серверный номер
_, err = client.PublishAuto(ctx, stream.ID, []runnev.Event{{"type": "tick"}})

// сырые байты для потока в режиме raw
_, err = client.PublishRaw(ctx, stream.ID, 9001, protobufBytes, "application/octet-stream")

Подписка

Subscribe возвращает *Subscription, предоставляющий канал только для приёма, доступ к ошибке и Close. Он переподключается автоматически, возобновляя с последнего номера.

go
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

sub, err := client.Subscribe(ctx, stream.ID, runnev.SubscribeOptions{Cursor: "0"})
if err != nil {
    log.Fatal(err)
}
defer sub.Close()

for batch := range sub.C {
    fmt.Println(batch.Seq, batch.Events)
}
if err := sub.Err(); err != nil {
    log.Println("subscription ended:", err)
}

Обработка ошибок

go
res, err := client.Publish(ctx, id, seq, events)
if err != nil {
    var rerr *runnev.Error
    if errors.As(err, &rerr) {
        log.Printf("code=%s status=%d request_id=%s", rerr.Code, rerr.Status, rerr.RequestID)
    }
    if errors.Is(err, runnev.ErrRateLimited) {
        time.Sleep(rerr.RetryAfter)
    }
}

*runnev.Error несёт Type, Code, Message, RequestID, Status и DocURL. Сигнальные значения для распространённых кодов (ErrRateLimited, ErrStreamNotFound, ErrInvalidAPIKey и другие) работают с errors.Is.

Поверхность API

МетодВозвращает
CreateStream(ctx, CreateStreamParams)(*Stream, error)
ListStreams(ctx, ListParams)(*StreamPage, error)
GetStream(ctx, id)(*Stream, error)
DeleteStream(ctx, id)error
Publish(ctx, id, seq, events)(*PublishResult, error)
PublishRaw(ctx, id, seq, data, contentType)(*PublishResult, error)
PublishAuto(ctx, id, events)(*PublishResult, error)
Cursor(ctx, id)(*CursorInfo, error)
Batch(ctx, id, seq)(*Batch, error)
Subscribe(ctx, id, SubscribeOptions)(*Subscription, error)

Запускаемые примеры: examples/publish и examples/subscribe.