1
1
import { Duplex } from 'node:stream' ;
2
2
3
3
import pMap from 'p-map' ;
4
+ import pQueue from 'p-queue' ;
4
5
import pTimeout from 'p-timeout' ;
5
6
import type { Logger } from 'winston' ;
6
7
@@ -39,26 +40,22 @@ export enum Strategy {
39
40
}
40
41
41
42
class TableResolverStream extends Duplex {
42
- queue : unknown [ ] = [ ] ;
43
-
44
43
constructor ( ) {
45
44
super ( { objectMode : true } ) ;
46
45
}
47
46
48
- _read ( ) {
49
- while ( this . queue . length > 0 ) {
50
- this . push ( this . queue . shift ( ) ) ;
51
- }
52
- if ( this . writableEnded ) {
53
- // end readable stream if writable stream has ended
54
- this . push ( null ) ;
55
- }
56
- }
47
+ _read ( ) { }
57
48
58
49
_write ( chunk : unknown , _ : string , next : ( error ?: Error | null ) => void ) {
59
- this . queue . push ( chunk ) ;
50
+ this . emit ( 'data' , chunk ) ;
60
51
next ( ) ;
61
52
}
53
+
54
+ end ( callback ?: ( ) => void ) : this {
55
+ this . emit ( 'end' ) ;
56
+ callback ?.( ) ;
57
+ return this ;
58
+ }
62
59
}
63
60
64
61
const validateResource = ( resource : Resource ) => {
@@ -92,20 +89,8 @@ const resolveTable = async (
92
89
) => {
93
90
logger . info ( `resolving table ${ table . name } ` ) ;
94
91
const stream = new TableResolverStream ( ) ;
95
- try {
96
- await table . resolver ( client , parent , stream ) ;
97
- } catch ( error ) {
98
- const tableError = new SyncTableResolveError ( `error resolving table ${ table . name } ` , {
99
- cause : error ,
100
- props : { table, client } ,
101
- } ) ;
102
- logger . error ( `error resolving table ${ table . name } ` , tableError ) ;
103
- return ;
104
- } finally {
105
- stream . end ( ) ;
106
- }
107
92
108
- for await ( const data of stream ) {
93
+ const processData = async ( data : unknown ) => {
109
94
logger . debug ( `resolving resource for table ${ table . name } ` ) ;
110
95
const resolveResourceTimeout = 10 * 60 * 1000 ;
111
96
const resource = new Resource ( table , parent , data ) ;
@@ -118,7 +103,7 @@ const resolveTable = async (
118
103
props : { resource, table, client } ,
119
104
} ) ;
120
105
logger . error ( preResolverError ) ;
121
- continue ;
106
+ return ;
122
107
}
123
108
124
109
try {
@@ -128,7 +113,7 @@ const resolveTable = async (
128
113
await pTimeout ( allColumnsPromise , { milliseconds : resolveResourceTimeout } ) ;
129
114
} catch ( error ) {
130
115
logger . error ( `error resolving columns for table ${ table . name } ` , error ) ;
131
- continue ;
116
+ return ;
132
117
}
133
118
134
119
try {
@@ -139,7 +124,7 @@ const resolveTable = async (
139
124
props : { resource, table, client } ,
140
125
} ) ;
141
126
logger . error ( postResolveError ) ;
142
- continue ;
127
+ return ;
143
128
}
144
129
145
130
setCQId ( resource , deterministicCQId ) ;
@@ -148,7 +133,7 @@ const resolveTable = async (
148
133
validateResource ( resource ) ;
149
134
} catch ( error ) {
150
135
logger . error ( error ) ;
151
- continue ;
136
+ return ;
152
137
}
153
138
154
139
try {
@@ -161,14 +146,36 @@ const resolveTable = async (
161
146
} ,
162
147
} ) ;
163
148
logger . error ( encodeError ) ;
164
- continue ;
149
+ return ;
165
150
}
166
151
167
152
logger . debug ( `done resolving resource for table ${ table . name } ` ) ;
168
153
169
154
await pMap ( table . relations , ( child ) =>
170
155
resolveTable ( logger , client , child , resource , syncStream , deterministicCQId ) ,
171
156
) ;
157
+ } ;
158
+
159
+ const queue = new pQueue ( { concurrency : 5 } ) ;
160
+
161
+ stream . on ( 'data' , async ( data ) => {
162
+ await queue . add ( ( ) => processData ( data ) ) ;
163
+ } ) ;
164
+
165
+ const resolverPromise = table . resolver ( client , parent , stream ) ;
166
+
167
+ try {
168
+ await resolverPromise ;
169
+ } catch ( error ) {
170
+ const tableError = new SyncTableResolveError ( `error resolving table ${ table . name } ` , {
171
+ cause : error ,
172
+ props : { table, client } ,
173
+ } ) ;
174
+ logger . error ( `error resolving table ${ table . name } ` , tableError ) ;
175
+ return ;
176
+ } finally {
177
+ stream . end ( ) ;
178
+ await queue . onIdle ( ) ;
172
179
}
173
180
174
181
logger . info ( `done resolving table ${ table . name } ` ) ;
0 commit comments