mcpField
S
serverpod-streams

serverpod-streams

github.com/serverpod開発3.3k44 回インストール1 日前に更新
リポジトリ

serverpod-streams について

ストリームを受け取る、または返すエンドポイントメソッドを定義する Serverpod 向けスキルです。WebSocket 管理のクライアントスタブを生成し、クライアントとエンドポイント間のストリーミングを構築できます。

主な機能

  1. 01ストリーム引数と戻り値
  2. 02WebSocket 管理のクライアントスタブ
  3. 03serverpod generate によるスタブ生成
  4. 04ストリームのライフサイクルとキャンセル処理
  5. 05シリアライズ可能な例外の伝播

活用シーン

  1. 01エンドポイントからクライアントメッセージを返送
  2. 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;
    }
  }
}

コメント