1
1
import { Service } from 'typedi' ;
2
+ import { FlowObjectFilterGrouped } from '../../../flow-object/model' ;
2
3
import { FlowService } from '../../flow-service' ;
3
4
import type { FlowWhere , UniqueFlowEntity } from '../../model' ;
4
5
import type {
@@ -18,6 +19,7 @@ import {
18
19
parseFlowIdVersionSet ,
19
20
prepareFlowConditions ,
20
21
prepareFlowStatusConditions ,
22
+ stringifyFlowIdVersionArray ,
21
23
} from './utils' ;
22
24
23
25
@Service ( )
@@ -50,47 +52,37 @@ export class SearchFlowByFiltersStrategy implements FlowSearchStrategy {
50
52
// to be able to sort the flows using the entity
51
53
const isSortByEntity = orderBy && orderBy . entity !== 'flow' ;
52
54
let sortByFlowIDsSet = new Set < string > ( ) ;
55
+ let sortByFlowIDsPromise : Promise < UniqueFlowEntity [ ] > = Promise . resolve ( [ ] ) ;
53
56
const orderByForFlow = mapFlowOrderBy ( orderBy ) ;
54
57
55
58
// Fetch sorted flow IDs only for the filtered subset instead of the whole table
56
59
if ( isSortByEntity ) {
57
60
// Get entity-sorted IDs then intersect with filtered subset
58
- const sortByFlowIDs = await this . flowService . getFlowIDsFromEntity (
61
+ sortByFlowIDsPromise = this . flowService . getFlowIDsFromEntity (
59
62
models ,
60
63
orderBy
61
64
) ;
62
- sortByFlowIDsSet = new Set (
63
- [ ...sortByFlowIDs ] . map ( ( o ) => `${ o . id } :${ o . versionID } ` )
64
- ) ;
65
65
} else {
66
66
// Let the DB sort only the filtered IDs
67
- const sortByFlowIDs = await this . flowService . getFlows ( {
67
+ sortByFlowIDsPromise = this . flowService . getFlows ( {
68
68
models,
69
69
orderBy : orderByForFlow ,
70
70
} ) ;
71
- sortByFlowIDsSet = new Set (
72
- [ ...sortByFlowIDs ] . map ( ( o ) => `${ o . id } :${ o . versionID } ` )
73
- ) ;
74
71
}
75
72
// We need to fetch the flowIDs by the nestedFlowFilters
76
73
// if there are any
77
74
const isFilterByNestedFilters = nestedFlowFilters !== undefined ;
78
75
let flowIDsFromNestedFlowFiltersSet = new Set < string > ( ) ;
79
-
76
+ let flowsFromNestedFiltersPromise : Promise < FlowIdSearchStrategyResponse > =
77
+ Promise . resolve ( { flows : [ ] } ) ;
78
+ let didFlowsFromNestedFiltersPromiseCreated = false ;
80
79
if ( isFilterByNestedFilters ) {
81
- const { flows } : FlowIdSearchStrategyResponse =
82
- await this . getFlowIdsFromNestedFlowFilters . search ( {
80
+ flowsFromNestedFiltersPromise =
81
+ this . getFlowIdsFromNestedFlowFilters . search ( {
83
82
models,
84
83
nestedFlowFilters,
85
84
} ) ;
86
-
87
- // If after this filter we have no flows, we can return an empty array
88
- if ( flows . length === 0 ) {
89
- return { flows : [ ] , count : 0 } ;
90
- }
91
- flowIDsFromNestedFlowFiltersSet = new Set (
92
- [ ...flows ] . map ( ( o ) => `${ o . id } :${ o . versionID } ` )
93
- ) ;
85
+ didFlowsFromNestedFiltersPromiseCreated = true ;
94
86
}
95
87
96
88
// Now we need to check if we need to filter by category
@@ -103,67 +95,43 @@ export class SearchFlowByFiltersStrategy implements FlowSearchStrategy {
103
95
isSearchByCategoryShotcut || flowCategoryFilters ?. length > 0 ;
104
96
105
97
let flowIDsFromCategoryFiltersSet = new Set < string > ( ) ;
98
+ let flowsFromCategoryFiltersPromise : Promise < FlowIdSearchStrategyResponse > =
99
+ Promise . resolve ( { flows : [ ] } ) ;
100
+ let didFlowsFromCategoryFiltersPromiseCreated = false ;
106
101
107
102
if ( isFilterByCategory ) {
108
- const { flows } : FlowIdSearchStrategyResponse =
109
- await this . getFlowIdsFromCategoryConditions . search ( {
103
+ flowsFromCategoryFiltersPromise =
104
+ this . getFlowIdsFromCategoryConditions . search ( {
110
105
models,
111
106
flowCategoryConditions : flowCategoryFilters ?? [ ] ,
112
107
shortcutFilters,
113
108
} ) ;
114
-
115
- // If after this filter we have no flows, we can return an empty array
116
- if ( flows . length === 0 ) {
117
- return { flows : [ ] , count : 0 } ;
118
- }
119
-
120
- flowIDsFromCategoryFiltersSet = new Set (
121
- [ ...flows ] . map ( ( o ) => `${ o . id } :${ o . versionID } ` )
122
- ) ;
109
+ didFlowsFromCategoryFiltersPromiseCreated = true ;
123
110
}
124
111
125
112
// After that, if we need to filter by flowObjects
126
113
// Obtain the flowIDs from the flowObjects
127
114
const isFilterByFlowObjects = flowObjectFilters ?. length > 0 ;
128
115
129
116
let flowIDsFromObjectFiltersSet = new Set < string > ( ) ;
117
+ let flowsFromObjectFiltersPromise : Promise < FlowIdSearchStrategyResponse > =
118
+ Promise . resolve ( { flows : [ ] } ) ;
119
+ let didFlowsFromObjectFiltersPromiseCreated = false ;
120
+ let flowObjectFiltersGrouped : FlowObjectFilterGrouped | null = null ;
130
121
131
122
if ( isFilterByFlowObjects ) {
132
123
// Firts step is to map the filters to the FlowObjectFiltersGrouped
133
124
// To allow doing inclusive filtering between filters of the same type+direction
134
125
// But exclusive filtering between filters of different type+direction
135
- const flowObjectFiltersGrouped =
126
+ flowObjectFiltersGrouped =
136
127
mapFlowFiltersToFlowObjectFiltersGrouped ( flowObjectFilters ) ;
137
128
138
- const { flows : flowsFromObjectFilters } : FlowIdSearchStrategyResponse =
139
- await this . getFlowIdsFromObjectConditions . search ( {
129
+ flowsFromObjectFiltersPromise =
130
+ this . getFlowIdsFromObjectConditions . search ( {
140
131
models,
141
132
flowObjectFilterGrouped : flowObjectFiltersGrouped ,
142
133
} ) ;
143
-
144
- // If after this filter we have no flows, we can return an empty array
145
- if ( flowsFromObjectFilters . length === 0 ) {
146
- return { flows : [ ] , count : 0 } ;
147
- }
148
-
149
- // If 'includeChildrenOfParkedFlows' is defined and true
150
- // we need to obtain the flowIDs from the childs whose parent flows are parked
151
- if ( shouldIncludeChildrenOfParkedFlows ) {
152
- // We need to obtain the flowIDs from the childs whose parent flows are parked
153
- const childs =
154
- await this . flowService . getParkedParentFlowsByFlowObjectFilter (
155
- models ,
156
- flowObjectFiltersGrouped
157
- ) ;
158
-
159
- for ( const child of childs ) {
160
- flowsFromObjectFilters . push ( child ) ;
161
- }
162
- }
163
-
164
- flowIDsFromObjectFiltersSet = new Set (
165
- [ ...flowsFromObjectFilters ] . map ( ( o ) => `${ o . id } :${ o . versionID } ` )
166
- ) ;
134
+ didFlowsFromObjectFiltersPromiseCreated = true ;
167
135
}
168
136
169
137
// Lastly, we need to check if we need to filter by flow
@@ -173,6 +141,9 @@ export class SearchFlowByFiltersStrategy implements FlowSearchStrategy {
173
141
const isFilterByFlowStatus = statusFilter !== undefined ;
174
142
175
143
let flowIDsFromFlowFiltersSet = new Set < string > ( ) ;
144
+ let flowsFromFlowFiltersPromise : Promise < UniqueFlowEntity [ ] > =
145
+ Promise . resolve ( [ ] ) ;
146
+ let didFlowsFromFlowFiltersPromiseCreated = false ;
176
147
177
148
if ( isFilterByFlow || isFilterByFlowStatus ) {
178
149
let flowConditions : FlowWhere = prepareFlowConditions ( flowFilters ) ;
@@ -182,21 +153,90 @@ export class SearchFlowByFiltersStrategy implements FlowSearchStrategy {
182
153
statusFilter
183
154
) ;
184
155
185
- const flows : UniqueFlowEntity [ ] = await this . flowService . getFlows ( {
156
+ flowsFromFlowFiltersPromise = this . flowService . getFlows ( {
186
157
models,
187
158
conditions : flowConditions ,
188
159
} ) ;
160
+ didFlowsFromFlowFiltersPromiseCreated = true ;
161
+ }
189
162
190
- // If after this filter we have no flows, we can return an empty array
191
- if ( flows . length === 0 ) {
192
- return { flows : [ ] , count : 0 } ;
193
- }
163
+ // Now we need to wait for all the promises to be resolved
164
+ const [
165
+ flowsFromCategoryFilters ,
166
+ flowsFromNestedFilters ,
167
+ flowsFromObjectFilters ,
168
+ flowsFromFlowFilters ,
169
+ sortByFlowIDs ,
170
+ ] = await Promise . all ( [
171
+ flowsFromCategoryFiltersPromise ,
172
+ flowsFromNestedFiltersPromise ,
173
+ flowsFromObjectFiltersPromise ,
174
+ flowsFromFlowFiltersPromise ,
175
+ sortByFlowIDsPromise ,
176
+ ] ) ;
194
177
195
- flowIDsFromFlowFiltersSet = new Set (
196
- [ ...flows ] . map ( ( o ) => `${ o . id } :${ o . versionID } ` )
197
- ) ;
178
+ // First check if we have created the promises
179
+ // and if so, check if the flows are empty
180
+ // If they are empty, we can return an empty array
181
+ // and a count of 0
182
+ if (
183
+ didFlowsFromNestedFiltersPromiseCreated &&
184
+ flowsFromNestedFilters . flows . length === 0
185
+ ) {
186
+ return { flows : [ ] , count : 0 } ;
198
187
}
199
188
189
+ if (
190
+ didFlowsFromCategoryFiltersPromiseCreated &&
191
+ flowsFromCategoryFilters . flows . length === 0
192
+ ) {
193
+ return { flows : [ ] , count : 0 } ;
194
+ }
195
+ if (
196
+ didFlowsFromObjectFiltersPromiseCreated &&
197
+ flowsFromObjectFilters . flows . length === 0
198
+ ) {
199
+ return { flows : [ ] , count : 0 } ;
200
+ }
201
+
202
+ if (
203
+ didFlowsFromFlowFiltersPromiseCreated &&
204
+ flowsFromFlowFilters . length === 0
205
+ ) {
206
+ return { flows : [ ] , count : 0 } ;
207
+ }
208
+
209
+ // Now we need to obtain the flowIDs from the flows filtering promises
210
+ flowIDsFromNestedFlowFiltersSet = stringifyFlowIdVersionArray (
211
+ flowsFromNestedFilters . flows
212
+ ) ;
213
+ flowIDsFromCategoryFiltersSet = stringifyFlowIdVersionArray (
214
+ flowsFromCategoryFilters . flows
215
+ ) ;
216
+
217
+ // If 'includeChildrenOfParkedFlows' is defined and true
218
+ // we need to obtain the flowIDs from the childs whose parent flows are parked
219
+ // if (shouldIncludeChildrenOfParkedFlows) {
220
+ // We need to obtain the flowIDs from the childs whose parent flows are parked
221
+ if ( shouldIncludeChildrenOfParkedFlows && flowObjectFiltersGrouped ) {
222
+ const childs =
223
+ await this . flowService . getParkedParentFlowsByFlowObjectFilter (
224
+ models ,
225
+ flowObjectFiltersGrouped
226
+ ) ;
227
+
228
+ for ( const child of childs ) {
229
+ flowsFromObjectFilters . flows . push ( child ) ;
230
+ }
231
+ }
232
+ flowIDsFromObjectFiltersSet = stringifyFlowIdVersionArray (
233
+ flowsFromObjectFilters . flows
234
+ ) ;
235
+ flowIDsFromFlowFiltersSet =
236
+ stringifyFlowIdVersionArray ( flowsFromFlowFilters ) ;
237
+ // Lastly, we need to obtain the flowIDs from the sortByFlowIDs
238
+ sortByFlowIDsSet = stringifyFlowIdVersionArray ( sortByFlowIDs ) ;
239
+
200
240
// We need to intersect the flowIDs from the flowObjects, flowCategoryFilters and flowFilters
201
241
// to obtain the flowIDs that match all the filters
202
242
const intersectedFlows : Set < string > = intersectSets (
@@ -209,13 +249,16 @@ export class SearchFlowByFiltersStrategy implements FlowSearchStrategy {
209
249
if ( intersectedFlows . size === 0 ) {
210
250
return { flows : [ ] , count : 0 } ;
211
251
}
212
-
252
+
213
253
// The method Set.prototype.intersection(...) compares the bigger set with the smaller one
214
254
// and returns the smaller one, so we need to do the opposite
215
255
// More likely the `sortedFlows` will be smaller than the `intersectedFlows`,
216
256
// since `intersectedFlows` is the intersection of all the filters
217
257
// so we need to reverse the list of `sortedFlows`
218
- const sortedFlows : Set < string > = intersectSets ( intersectedFlows , sortByFlowIDsSet ) ;
258
+ const sortedFlows : Set < string > = intersectSets (
259
+ intersectedFlows ,
260
+ sortByFlowIDsSet
261
+ ) ;
219
262
const parsedSortedFlows = parseFlowIdVersionSet ( sortedFlows ) . reverse ( ) ;
220
263
221
264
const count = sortedFlows . size ;
0 commit comments