@@ -2,65 +2,48 @@ export type MetadataOptions<T> = {
22 baseUrl : string ;
33 runId : string ;
44 key : string ;
5- iterator : AsyncIterator < T > ;
5+ source : AsyncIterable < T > ;
66 headers ?: Record < string , string > ;
77 signal ?: AbortSignal ;
88 version ?: "v1" | "v2" ;
99} ;
1010
1111export class MetadataStream < T > {
1212 private controller = new AbortController ( ) ;
13- private serverQueue : Array < Promise < IteratorResult < T > > > = [ ] ;
14- private consumerQueue : Array < Promise < IteratorResult < T > > > = [ ] ;
15- private serverIterator : AsyncIterator < T > ;
16- private consumerIterator : AsyncIterator < T > ;
13+ private serverStream : ReadableStream < T > ;
14+ private consumerStream : ReadableStream < T > ;
1715 private streamPromise : Promise < void | Response > ;
1816
1917 constructor ( private options : MetadataOptions < T > ) {
20- const { serverIterator , consumerIterator } = this . createTeeIterators ( ) ;
21- this . serverIterator = serverIterator ;
22- this . consumerIterator = consumerIterator ;
18+ const [ serverStream , consumerStream ] = this . createTeeStreams ( ) ;
19+ this . serverStream = serverStream ;
20+ this . consumerStream = consumerStream ;
2321
2422 this . streamPromise = this . initializeServerStream ( ) ;
2523 }
2624
27- private createTeeIterators ( ) {
28- const teeIterator = ( queue : Array < Promise < IteratorResult < T > > > ) : AsyncIterator < T > => ( {
29- next : ( ) => {
30- if ( queue . length === 0 ) {
31- const result = this . options . iterator . next ( ) ;
32- this . serverQueue . push ( result ) ;
33- this . consumerQueue . push ( result ) ;
25+ private createTeeStreams ( ) {
26+ const readableSource = new ReadableStream < T > ( {
27+ start : async ( controller ) => {
28+ for await ( const value of this . options . source ) {
29+ controller . enqueue ( value ) ;
3430 }
35- return queue . shift ( ) ! ;
31+
32+ controller . close ( ) ;
3633 } ,
3734 } ) ;
3835
39- return {
40- serverIterator : teeIterator ( this . serverQueue ) ,
41- consumerIterator : teeIterator ( this . consumerQueue ) ,
42- } ;
36+ return readableSource . tee ( ) ;
4337 }
4438
45- private initializeServerStream ( ) : Promise < void | Response > {
46- const serverIterator = this . serverIterator ;
47-
48- const serverStream = new ReadableStream ( {
49- async pull ( controller ) {
50- try {
51- const { value, done } = await serverIterator . next ( ) ;
52- if ( done ) {
53- controller . close ( ) ;
54- return ;
55- }
56-
57- controller . enqueue ( JSON . stringify ( value ) + "\n" ) ;
58- } catch ( err ) {
59- controller . error ( err ) ;
60- }
61- } ,
62- cancel : ( ) => this . controller . abort ( ) ,
63- } ) ;
39+ private initializeServerStream ( ) : Promise < Response > {
40+ const serverStream = this . serverStream . pipeThrough (
41+ new TransformStream < T , string > ( {
42+ async transform ( chunk , controller ) {
43+ controller . enqueue ( JSON . stringify ( chunk ) + "\n" ) ;
44+ } ,
45+ } )
46+ ) ;
6447
6548 return fetch (
6649 `${ this . options . baseUrl } /realtime/${ this . options . version ?? "v1" } /streams/${
@@ -82,6 +65,19 @@ export class MetadataStream<T> {
8265 }
8366
8467 public [ Symbol . asyncIterator ] ( ) {
85- return this . consumerIterator ;
68+ return streamToAsyncIterator ( this . consumerStream ) ;
69+ }
70+ }
71+
72+ async function * streamToAsyncIterator < T > ( stream : ReadableStream < T > ) : AsyncIterableIterator < T > {
73+ const reader = stream . getReader ( ) ;
74+ try {
75+ while ( true ) {
76+ const { done, value } = await reader . read ( ) ;
77+ if ( done ) return ;
78+ yield value ;
79+ }
80+ } finally {
81+ reader . releaseLock ( ) ;
8682 }
8783}
0 commit comments