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

# リアルタイムストリーム

> Server-Sent Events (SSE) ストリームを通して、ライブのアプリケーションイベントをサブスクライブします。

`api.ApplicationRealtime(appID)` は [Server-Sent Events](https://developer.mozilla.org/docs/Web/API/Server-sent_events) ストリームを開き、`*rest.RealtimeStream` を返します。`io.EOF` になるまで `stream.Next()` で反復処理してください。

```go theme={null}
client := rest.NewClient(os.Getenv("SQUARECLOUD_API_KEY"))
defer client.Close()

api := rest.New(client)
```

## ストリームの消費

```go theme={null}
stream, err := api.ApplicationRealtime("abc123def456abc123def456")
if err != nil {
	panic(err)
}
defer stream.Close()

for {
	event, err := stream.Next()
	if err == io.EOF {
		break // ストリーム終了（例: 10分の TTL に到達）
	}
	if err != nil {
		panic(err)
	}

	fmt.Println(event.Name, string(event.Data))
}
```

常に `defer stream.Close()` を呼び出してください — 閉じられていないストリームは、アカウントの接続スロットを 1 つ占有し続けます。

## イベントの形式

ストリームは 2 種類のフレームを発行します:

* **システムイベント** — 接続ライフサイクルのメッセージ: `REALTIME_CONNECTING`、`REALTIME_TIMEOUT`、`REALTIME_DISCONNECTED`、`REALTIME_RECONNECT`、`REALTIME_ERROR`。
* **`message` イベント** — アプリケーションのペイロード。`Data` は SDK にとって不透明で、通常は JSON です — 自分でアンマーシャルしてください:

```go theme={null}
if event.Name == "message" {
	var payload map[string]any
	if err := json.Unmarshal(event.Data, &payload); err == nil {
		fmt.Println(payload)
	}
}
```

## 接続の上限

<Warning>
  1 つのアカウントで同時に開けるのは最大 **5 接続** で、各接続は最大 **10 分間**（TTL）持続します。TTL に達するとストリームは `io.EOF` で終了します — サブスクライブを継続するには、ループで再接続してください。
</Warning>

```go theme={null}
for {
	stream, err := api.ApplicationRealtime("abc123def456abc123def456")
	if err != nil {
		panic(err)
	}

	for {
		event, err := stream.Next()
		if err != nil {
			break // TTL 到達時の io.EOF — 再接続する
		}
		fmt.Println(event.Name, string(event.Data))
	}

	stream.Close()
}
```

## キャンセル

`rest.WithContext` で `context.Context` を付与すると、外部からストリームを停止できます:

```go theme={null}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

stream, err := api.ApplicationRealtime("abc123def456abc123def456", rest.WithContext(ctx))
if err != nil {
	panic(err)
}
defer stream.Close()

// 別のゴルーチンから cancel() を呼ぶとストリームが終了する
```
