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