import type { NotificationService } from '@cloudbeaver/core-events' ; import { AsyncTaskInfo , GraphQLService , ServerInternalError , DataTransferParameters } from '@cloudbeaver/core-sdk' ; import { CancellablePromise , cancellableTimeout , Deferred , EDeferredState } from '@cloudbeaver/core-utils' ; const DELAY_BETWEEN_TRIES = 1000 ; export class ExportFromContainerProcess extends Deferred < string > { private taskId ? : string ; private timeout ? : CancellablePromise < void > ; private isCancelConfirmed = false ; constructor ( private graphQLService , private notificationService ) { super ( ) ; } async start ( connectionId , containerNodePath , parameters ) { try { const { taskInfo } = await this . graphQLService . sdk . exportDataFromContainer ( { connectionId , containerNodePath , parameters , } ) ; await this . applyResult ( taskInfo ) ; this . taskId = taskInfo . id ; if ( this . getState ( ) === EDeferredState . CANCELLING ) { await this . cancelAsync ( this . taskId ) ; } this . statusUpdateProcess ( ) ; return this . taskId ; } catch ( e ) { this . onError ( e ) ; throw e ; } } /**
     * this method just mark process as cancelling
     * to avoid racing conditions the server request will be executed in synchronous manner in start method
     */ cancel ( ) { if ( this . getState ( ) !== EDeferredState . PENDING ) { return ; } this . toCancelling ( ) ; if ( this . timeout ) { this . timeout . cancel ( ) ; } } private async statusUpdateProcess ( ) { if ( this . isFinished || ! this . taskId ) { return ; } while ( this . isInProgress ) { if ( this . getState ( ) === EDeferredState . CANCELLING ) { await this . cancelAsync ( this . taskId ) ; } try { const { taskInfo } = await this . graphQLService . sdk . getAsyncTaskInfo ( { taskId : this . taskId , removeOnFinish : false , } ) ; await this . applyResult ( taskInfo ) ; if ( this . isFinished ) { return ; } } catch ( e ) { this . notificationService . logException ( e , 'Failed to check async task status' ) ; } try { this . timeout = cancellableTimeout ( DELAY_BETWEEN_TRIES ) ; await this . timeout ; } catch { } } } private async cancelAsync ( taskId ) { if ( this . isCancelConfirmed ) { return ; } try { await this . graphQLService . sdk . asyncTaskCancel ( { taskId } ) ; this . isCancelConfirmed = true ; } catch ( e ) { if ( this . getState ( ) === EDeferredState . CANCELLING ) { this . toPending ( ) ; this . notificationService . logException ( e , 'Failed to cancel async task' ) ; } } } private async applyResult ( taskInfo ) { if ( taskInfo . running ) { return ; } if ( taskInfo . error ) { const serverError = new ServerInternalError ( taskInfo . error ) ; this . onError ( serverError , taskInfo . status ) ; return ; } if ( ! taskInfo . taskResult ) { this . onError ( new Error ( 'Tasks execution returns no taskResult' ) , taskInfo . status ) ; return ; } this . toResolved ( taskInfo . taskResult ) ; await this . graphQLService . sdk . getAsyncTaskInfo ( { taskId : taskInfo . id , removeOnFinish : true } ) ; } private onError ( error , status ? ) { if ( this . getState ( ) === EDeferredState . CANCELLING ) { this . toCancelled ( error ) ; } else { this . toRejected ( error ) ; } } }