@@ -60,18 +60,48 @@ const buildInferenceMetadata = ({ types }) =>
60
60
// TODO: use async iterators when we switch to node>=10
61
61
// or better investigate if we can offload metadata building to worker/Jobs API
62
62
// and then feed the result into redux?
63
- const processNextType = ( ) => {
63
+ const processNextType = async ( ) => {
64
64
const typeName = typeNames . pop ( )
65
- store . dispatch ( {
66
- type : `BUILD_TYPE_METADATA` ,
67
- payload : {
68
- typeName,
69
- nodes : getDataStore ( ) . iterateNodesByType ( typeName ) ,
70
- } ,
71
- } )
65
+
66
+ let processingNodes = [ ]
67
+ let dispatchCount = 0
68
+ function dispatchNodes ( ) {
69
+ return new Promise ( res => {
70
+ store . dispatch ( {
71
+ type : `BUILD_TYPE_METADATA` ,
72
+ payload : {
73
+ typeName,
74
+ // only clear metadata on the first chunk for this type
75
+ clearExistingMetadata : dispatchCount ++ === 0 ,
76
+ nodes : processingNodes ,
77
+ } ,
78
+ } )
79
+ setImmediate ( ( ) => {
80
+ // clear this array after BUILD_TYPE_METADATA reducer has synchronously run
81
+ processingNodes = [ ]
82
+ // dont block the event loop. node may decide to free previous processingNodes array from memory if it needs to.
83
+ setImmediate ( ( ) => {
84
+ res ( null )
85
+ } )
86
+ } )
87
+ } )
88
+ }
89
+
90
+ for ( const node of getDataStore ( ) . iterateNodesByType ( typeName ) ) {
91
+ processingNodes . push ( node )
92
+
93
+ if ( processingNodes . length > 1000 ) {
94
+ await dispatchNodes ( )
95
+ }
96
+ }
97
+
98
+ if ( processingNodes . length > 0 ) {
99
+ await dispatchNodes ( )
100
+ }
101
+
72
102
if ( typeNames . length > 0 ) {
73
- // Give event-loop a break
74
- setTimeout ( processNextType , 0 )
103
+ // dont block the event loop
104
+ setImmediate ( ( ) => processNextType ( ) )
75
105
} else {
76
106
resolve ( )
77
107
}
0 commit comments