@@ -488,35 +488,43 @@ export class TypeORMWorkspaceDBImpl extends TransactionalDBImpl<WorkspaceDB> imp
488488 limit : number = 100 ,
489489 type : WorkspaceType = "regular" ,
490490 ) : Promise < WorkspaceOwnerAndDeletionEligibility [ ] > {
491- // we do not allow to run this with a future date
492491 if ( cutOffDate > new Date ( ) ) {
493492 throw new Error ( "cutOffDate must not be in the future, was: " + cutOffDate . toISOString ( ) ) ;
494493 }
495494 const workspaceRepo = await this . getWorkspaceRepo ( ) ;
496495 const qb = workspaceRepo
497496 . createQueryBuilder ( "ws" )
498- . select ( [ "ws.id" , "ws.ownerId" , "ws.deletionEligibilityTime" ] )
497+ . leftJoinAndMapOne (
498+ "ws.latestInstance" ,
499+ DBWorkspaceInstance ,
500+ "wsi" ,
501+ `wsi.id = (
502+ SELECT i.id
503+ FROM d_b_workspace_instance AS i
504+ WHERE i.workspaceId = ws.id
505+ ORDER BY i.creationTime DESC
506+ LIMIT 1
507+ )` ,
508+ )
509+ . select ( [ "ws.id" , "ws.ownerId" , "ws.deletionEligibilityTime" , "wsi.id" , "wsi.status" ] )
499510 . where ( "ws.deleted = :deleted" , { deleted : 0 } )
500511 . andWhere ( "ws.type = :type" , { type } )
501512 . andWhere ( "ws.softDeleted IS NULL" )
502513 . andWhere ( "ws.softDeletedTime = ''" )
503514 . andWhere ( "ws.pinned = :pinned" , { pinned : 0 } )
504515 . andWhere ( "ws.deletionEligibilityTime != ''" )
505516 . andWhere ( "ws.deletionEligibilityTime < :cutOffDate" , { cutOffDate : cutOffDate . toISOString ( ) } )
517+ // we don't want to delete workspaces that are active
518+ . andWhere (
519+ new Brackets ( ( qb ) => {
520+ qb . where ( "wsi.id IS NULL" ) . orWhere ( "JSON_UNQUOTE(wsi.status->>'$.phase') = :stoppedStatus" , {
521+ stoppedStatus : "stopped" ,
522+ } ) ;
523+ } ) ,
524+ )
506525 . limit ( limit ) ;
507526
508- const results : WorkspaceOwnerAndDeletionEligibility [ ] = await qb . getMany ( ) ;
509-
510- // hack to have an async filter predicate
511- const filtered = await Promise . all (
512- results . map ( async ( ws ) => {
513- // we don't want to delete workspaces that have a running instance
514- const latestInstance = await this . findRunningInstance ( ws . id ) ;
515- return { ws, keep : latestInstance === undefined } ;
516- } ) ,
517- ) ;
518-
519- return filtered . filter ( ( result ) => result . keep ) . map ( ( result ) => result . ws ) ;
527+ return qb . getMany ( ) ;
520528 }
521529
522530 public async findWorkspacesForPurging (
0 commit comments