serverpod-streams について
ストリームを受け取る、または返すエンドポイントメソッドを定義する Serverpod 向けスキルです。WebSocket 管理のクライアントスタブを生成し、クライアントとエンドポイント間のストリーミングを構築できます。
主な機能
- 01ストリーム引数と戻り値
- 02WebSocket 管理のクライアントスタブ
- 03serverpod generate によるスタブ生成
- 04ストリームのライフサイクルとキャンセル処理
- 05シリアライズ可能な例外の伝播
活用シーン
- 01エンドポイントからクライアントメッセージを返送
- 02サーバーからクライアントへのストリームメソッド構築
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ serverpod/ serverpod --skill serverpod-streamsインストール後、Claude Code で/serverpod-streamsを入力して読み込まれたか確認します。
詳細
Serverpod ストリーム
Stream<T> を受け取る、または返すエンドポイントメソッドでは、WebSocket で管理されるクライアントスタブが生成されます。型はシリアライズ可能である必要があります。
ストリームをサーバーイベントと併用するのは一般的なユースケースです。Server Events を参照してください。
ストリーミングメソッドの定義
class ExampleEndpoint extends Endpoint {
Stream<String> echoStream(Session session, Stream<String> stream) async* {
await for (var message in stream) {
yield message;
}
}
}
クライアントスタブを生成するには、serverpod generate を実行します。
クライアントでの使用方法
var inStream = StreamController<String>();
var outStream = client.example.echoStream(inStream.stream);
outStream.listen((message) => print('Received: $message'));
inStream.add('Hello');
処理が終わったら StreamController を閉じます。サブスクリプションをキャンセルすると、両側が閉じます。入出力ストリームは個別に使用できます(多くの場合、サーバーからのストリームだけで十分です)。必要に応じて、メソッドに複数のストリームパラメーターを指定できます。API の形を明確に保ち、変更後は再生成してください。
ライフサイクル
- 呼び出しごとにサーバー
Sessionが作成されます。戻り値がストリームのメソッドでは、返されたストリームが完了またはキャンセルされるまでセッションが維持されます。 - WebSocket の切断により、両側のストリームが閉じます。
- 戻り値がストリームのメソッドは、キャンセルまたは完了するまで維持されます。
エラー処理
シリアライズ可能な例外をスローするとストリームが閉じ、クライアントは onError でその例外を受け取ります。例外はどちらの方向にも伝播します。例外型は .spy.yaml で定義してください。
サーバーイベントと組み合わせた例(簡略版)
class PixelDrawingEndpoint extends Endpoint {
static const _channelPixelAdded = 'pixel-added';
final _pixelData = Uint8List(_numPixels);
Future<void> setPixel(
Session session, {
required int colorIndex,
required int pixelIndex,
}) async {
_pixelData[pixelIndex] = colorIndex;
// Notify all connected clients that we set a pixel, by posting a message
// to the _channelPixelAdded channel.
session.messages.postMessage(
_channelPixelAdded,
ImageUpdate(
pixelIndex: pixelIndex,
colorIndex: colorIndex,
),
);
}
/// Returns a stream of image updates. The first message will always be a
/// `ImageData` object, which contains the full image. Sequential updates
/// will be `ImageUpdate` objects, which contains a single updated pixel.
Stream imageUpdates(Session session) async* {
var updateStream =
session.messages.createStream<ImageUpdate>(_channelPixelAdded);
yield ImageData(
pixels: _pixelData.buffer.asByteData(),
width: _imageWidth,
height: _imageHeight,
);
await for (var imageUpdate in updateStream) {
yield imageUpdate;
}
}
}
コメント
Markdown 対応