55 * 2.0.
66 */
77
8- import { checkRunningSessions } from './check_running_sessions' ;
8+ import {
9+ checkRunningSessions as checkRunningSessions$ ,
10+ CheckRunningSessionsDeps ,
11+ } from './check_running_sessions' ;
912import {
1013 SearchSessionStatus ,
1114 SearchSessionSavedObjectAttributes ,
@@ -20,6 +23,13 @@ import {
2023 SavedObjectsDeleteOptions ,
2124 SavedObjectsClientContract ,
2225} from '../../../../../../src/core/server' ;
26+ import { Subject } from 'rxjs' ;
27+ import { takeUntil } from 'rxjs/operators' ;
28+
29+ jest . useFakeTimers ( ) ;
30+
31+ const checkRunningSessions = ( deps : CheckRunningSessionsDeps , config : SearchSessionsConfig ) =>
32+ checkRunningSessions$ ( deps , config ) . toPromise ( ) ;
2333
2434describe ( 'getSearchStatus' , ( ) => {
2535 let mockClient : any ;
@@ -32,6 +42,7 @@ describe('getSearchStatus', () => {
3242 maxUpdateRetries : 3 ,
3343 defaultExpiration : moment . duration ( 7 , 'd' ) ,
3444 trackingInterval : moment . duration ( 10 , 's' ) ,
45+ monitoringTaskTimeout : moment . duration ( 5 , 'm' ) ,
3546 management : { } as any ,
3647 } ;
3748 const mockLogger : any = {
@@ -41,11 +52,13 @@ describe('getSearchStatus', () => {
4152 } ;
4253
4354 const emptySO = {
44- persisted : false ,
45- status : SearchSessionStatus . IN_PROGRESS ,
46- created : moment ( ) . subtract ( moment . duration ( 3 , 'm' ) ) ,
47- touched : moment ( ) . subtract ( moment . duration ( 10 , 's' ) ) ,
48- idMapping : { } ,
55+ attributes : {
56+ persisted : false ,
57+ status : SearchSessionStatus . IN_PROGRESS ,
58+ created : moment ( ) . subtract ( moment . duration ( 3 , 'm' ) ) ,
59+ touched : moment ( ) . subtract ( moment . duration ( 10 , 's' ) ) ,
60+ idMapping : { } ,
61+ } ,
4962 } ;
5063
5164 beforeEach ( ( ) => {
@@ -171,6 +184,118 @@ describe('getSearchStatus', () => {
171184
172185 expect ( savedObjectsClient . find ) . toHaveBeenCalledTimes ( 2 ) ;
173186 } ) ;
187+
188+ test ( 'fetching is abortable' , async ( ) => {
189+ let i = 0 ;
190+ const abort$ = new Subject ( ) ;
191+ savedObjectsClient . find . mockImplementation ( ( ) => {
192+ return new Promise ( ( resolve ) => {
193+ if ( ++ i === 2 ) {
194+ abort$ . next ( ) ;
195+ }
196+ resolve ( {
197+ saved_objects : i <= 5 ? [ emptySO , emptySO , emptySO , emptySO , emptySO ] : [ ] ,
198+ total : 25 ,
199+ page : i ,
200+ } as any ) ;
201+ } ) ;
202+ } ) ;
203+
204+ await checkRunningSessions$ (
205+ {
206+ savedObjectsClient,
207+ client : mockClient ,
208+ logger : mockLogger ,
209+ } ,
210+ config
211+ )
212+ . pipe ( takeUntil ( abort$ ) )
213+ . toPromise ( ) ;
214+
215+ jest . runAllTimers ( ) ;
216+
217+ // if not for `abort$` then this would be called 6 times!
218+ expect ( savedObjectsClient . find ) . toHaveBeenCalledTimes ( 2 ) ;
219+ } ) ;
220+
221+ test ( 'sorting is by "touched"' , async ( ) => {
222+ savedObjectsClient . find . mockResolvedValueOnce ( {
223+ saved_objects : [ ] ,
224+ total : 0 ,
225+ } as any ) ;
226+
227+ await checkRunningSessions (
228+ {
229+ savedObjectsClient,
230+ client : mockClient ,
231+ logger : mockLogger ,
232+ } ,
233+ config
234+ ) ;
235+
236+ expect ( savedObjectsClient . find ) . toHaveBeenCalledWith (
237+ expect . objectContaining ( { sortField : 'touched' , sortOrder : 'asc' } )
238+ ) ;
239+ } ) ;
240+
241+ test ( 'sessions fetched in the beginning are processed even if sessions in the end fail' , async ( ) => {
242+ let i = 0 ;
243+ savedObjectsClient . find . mockImplementation ( ( ) => {
244+ return new Promise ( ( resolve , reject ) => {
245+ if ( ++ i === 2 ) {
246+ reject ( new Error ( 'Fake find error...' ) ) ;
247+ }
248+ resolve ( {
249+ saved_objects :
250+ i <= 5
251+ ? [
252+ i === 1
253+ ? {
254+ id : '123' ,
255+ attributes : {
256+ persisted : false ,
257+ status : SearchSessionStatus . IN_PROGRESS ,
258+ created : moment ( ) . subtract ( moment . duration ( 3 , 'm' ) ) ,
259+ touched : moment ( ) . subtract ( moment . duration ( 2 , 'm' ) ) ,
260+ idMapping : {
261+ 'map-key' : {
262+ strategy : ENHANCED_ES_SEARCH_STRATEGY ,
263+ id : 'async-id' ,
264+ } ,
265+ } ,
266+ } ,
267+ }
268+ : emptySO ,
269+ emptySO ,
270+ emptySO ,
271+ emptySO ,
272+ emptySO ,
273+ ]
274+ : [ ] ,
275+ total : 25 ,
276+ page : i ,
277+ } as any ) ;
278+ } ) ;
279+ } ) ;
280+
281+ await checkRunningSessions$ (
282+ {
283+ savedObjectsClient,
284+ client : mockClient ,
285+ logger : mockLogger ,
286+ } ,
287+ config
288+ ) . toPromise ( ) ;
289+
290+ jest . runAllTimers ( ) ;
291+
292+ expect ( savedObjectsClient . find ) . toHaveBeenCalledTimes ( 2 ) ;
293+
294+ // by checking that delete was called we validate that sessions from session that were successfully fetched were processed
295+ expect ( mockClient . asyncSearch . delete ) . toBeCalled ( ) ;
296+ const { id } = mockClient . asyncSearch . delete . mock . calls [ 0 ] [ 0 ] ;
297+ expect ( id ) . toBe ( 'async-id' ) ;
298+ } ) ;
174299 } ) ;
175300
176301 describe ( 'delete' , ( ) => {
0 commit comments