@@ -8,6 +8,7 @@ require('reflect-metadata');
88import { GitpodClient , GitpodServer , GitpodServiceImpl , WorkspaceInstanceUpdateListener } from '@gitpod/gitpod-protocol/lib/gitpod-service' ;
99import { JsonRpcProxyFactory } from '@gitpod/gitpod-protocol/lib/messaging/proxy-factory' ;
1010import { NavigatorContext , PullRequestContext , User } from '@gitpod/gitpod-protocol/lib/protocol' ;
11+ import { ErrorCodes } from '@gitpod/gitpod-protocol/lib/messaging/error' ;
1112import { GitpodHostUrl } from '@gitpod/gitpod-protocol/lib/util/gitpod-host-url' ;
1213import { ControlServiceClient } from '@gitpod/supervisor-api-grpc/lib/control_grpc_pb' ;
1314import { InfoServiceClient } from '@gitpod/supervisor-api-grpc/lib/info_grpc_pb' ;
@@ -29,7 +30,7 @@ import ReconnectingWebSocket from 'reconnecting-websocket';
2930import { URL } from 'url' ;
3031import * as util from 'util' ;
3132import * as vscode from 'vscode' ;
32- import { ConsoleLogger , listen as doListen } from 'vscode-ws-jsonrpc' ;
33+ import { CancellationToken , ConsoleLogger , listen as doListen } from 'vscode-ws-jsonrpc' ;
3334import WebSocket = require( 'ws' ) ;
3435
3536export class SupervisorConnection {
@@ -65,7 +66,7 @@ export class SupervisorConnection {
6566 }
6667}
6768
68- type UsedGitpodFunction = [ 'getWorkspace' , 'openPort' , 'stopWorkspace' , 'setWorkspaceTimeout' , 'getWorkspaceTimeout' , 'getLoggedInUser' , 'takeSnapshot' , 'controlAdmission' , 'sendHeartBeat' , 'trackEvent' ] ;
69+ type UsedGitpodFunction = [ 'getWorkspace' , 'openPort' , 'stopWorkspace' , 'setWorkspaceTimeout' , 'getWorkspaceTimeout' , 'getLoggedInUser' , 'takeSnapshot' , 'waitForSnapshot' , ' controlAdmission', 'sendHeartBeat' , 'trackEvent' ] ;
6970type Union < Tuple extends any [ ] , Union = never > = Tuple [ number ] | Union ;
7071export type GitpodConnection = Omit < GitpodServiceImpl < GitpodClient , GitpodServer > , 'server' > & {
7172 server : Pick < GitpodServer , Union < UsedGitpodFunction > >
@@ -203,7 +204,7 @@ export async function createGitpodExtensionContext(context: vscode.ExtensionCont
203204 const gitpodApi = workspaceInfo . getGitpodApi ( ) ! ;
204205
205206 const factory = new JsonRpcProxyFactory < GitpodServer > ( ) ;
206- const gitpodFunctions : UsedGitpodFunction = [ 'getWorkspace' , 'openPort' , 'stopWorkspace' , 'setWorkspaceTimeout' , 'getWorkspaceTimeout' , 'getLoggedInUser' , 'takeSnapshot' , 'controlAdmission' , 'sendHeartBeat' , 'trackEvent' ] ;
207+ const gitpodFunctions : UsedGitpodFunction = [ 'getWorkspace' , 'openPort' , 'stopWorkspace' , 'setWorkspaceTimeout' , 'getWorkspaceTimeout' , 'getLoggedInUser' , 'takeSnapshot' , 'waitForSnapshot' , ' controlAdmission', 'sendHeartBeat' , 'trackEvent' ] ;
207208 const gitpodService : GitpodConnection = new GitpodServiceImpl < GitpodClient , GitpodServer > ( factory . createProxy ( ) ) as any ;
208209 const gitpodScopes = new Set < string > ( [
209210 'resource:workspace::' + workspaceId + '::get/update' ,
@@ -365,12 +366,28 @@ export async function registerWorkspaceCommands(context: GitpodExtensionContext)
365366 ) ) ;
366367 context . subscriptions . push ( vscode . commands . registerCommand ( 'gitpod.takeSnapshot' , async ( ) => {
367368 try {
368- const snapshotId = await vscode . window . withProgress ( {
369+ let snapshotId = '' ;
370+ await vscode . window . withProgress ( {
369371 location : vscode . ProgressLocation . Notification ,
370372 cancellable : true ,
371373 title : 'Capturing workspace snapshot'
372- } , _ => {
373- return context . gitpod . server . takeSnapshot ( { workspaceId : context . info . getWorkspaceId ( ) /*, layoutData?*/ } ) ;
374+ } , async ( _ , cancelToken : CancellationToken ) => {
375+ snapshotId = await context . gitpod . server . takeSnapshot ( { workspaceId : context . info . getWorkspaceId ( ) /*, layoutData?*/ , dontWait : true } ) ;
376+
377+ while ( ! cancelToken . isCancellationRequested ) {
378+ try {
379+ await context . gitpod . server . waitForSnapshot ( snapshotId ) ;
380+ return ;
381+ } catch ( err ) {
382+ if ( err . code === ErrorCodes . SNAPSHOT_ERROR || err . code === ErrorCodes . NOT_FOUND ) {
383+ // this is indeed an error with snapshot creation itself, break here!
384+ throw err ;
385+ }
386+
387+ // other errors (like connection errors): retry
388+ await new Promise ( ( resolve ) => setTimeout ( resolve , 3000 ) ) ;
389+ }
390+ }
374391 } ) ;
375392 const hostname = context . info . getGitpodApi ( ) ! . getHost ( ) ;
376393 const uri = `https://${ hostname } #snapshot/${ snapshotId } ` ;
0 commit comments