@@ -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' ) ;
3435import { BaseGitpodAnalyticsEventPropeties , GitpodAnalyticsEvent } from './analytics' ;
3536import * as uuid from 'uuid' ;
@@ -68,7 +69,7 @@ export class SupervisorConnection {
6869 }
6970}
7071
71- type UsedGitpodFunction = [ 'getWorkspace' , 'openPort' , 'stopWorkspace' , 'setWorkspaceTimeout' , 'getWorkspaceTimeout' , 'getLoggedInUser' , 'takeSnapshot' , 'controlAdmission' , 'sendHeartBeat' , 'trackEvent' ] ;
72+ type UsedGitpodFunction = [ 'getWorkspace' , 'openPort' , 'stopWorkspace' , 'setWorkspaceTimeout' , 'getWorkspaceTimeout' , 'getLoggedInUser' , 'takeSnapshot' , 'waitForSnapshot' , ' controlAdmission', 'sendHeartBeat' , 'trackEvent' ] ;
7273type Union < Tuple extends any [ ] , Union = never > = Tuple [ number ] | Union ;
7374export type GitpodConnection = Omit < GitpodServiceImpl < GitpodClient , GitpodServer > , 'server' > & {
7475 server : Pick < GitpodServer , Union < UsedGitpodFunction > >
@@ -237,7 +238,7 @@ export async function createGitpodExtensionContext(context: vscode.ExtensionCont
237238 const gitpodApi = workspaceInfo . getGitpodApi ( ) ! ;
238239
239240 const factory = new JsonRpcProxyFactory < GitpodServer > ( ) ;
240- const gitpodFunctions : UsedGitpodFunction = [ 'getWorkspace' , 'openPort' , 'stopWorkspace' , 'setWorkspaceTimeout' , 'getWorkspaceTimeout' , 'getLoggedInUser' , 'takeSnapshot' , 'controlAdmission' , 'sendHeartBeat' , 'trackEvent' ] ;
241+ const gitpodFunctions : UsedGitpodFunction = [ 'getWorkspace' , 'openPort' , 'stopWorkspace' , 'setWorkspaceTimeout' , 'getWorkspaceTimeout' , 'getLoggedInUser' , 'takeSnapshot' , 'waitForSnapshot' , ' controlAdmission', 'sendHeartBeat' , 'trackEvent' ] ;
241242 const gitpodService : GitpodConnection = new GitpodServiceImpl < GitpodClient , GitpodServer > ( factory . createProxy ( ) ) as any ;
242243 const gitpodScopes = new Set < string > ( [
243244 'resource:workspace::' + workspaceId + '::get/update' ,
@@ -474,13 +475,33 @@ export async function registerWorkspaceCommands(context: GitpodExtensionContext)
474475 properties : { action : 'snapshot' }
475476 } ) ;
476477 try {
477- const snapshotId = await vscode . window . withProgress ( {
478+ let snapshotId : string | undefined = undefined ;
479+ await vscode . window . withProgress ( {
478480 location : vscode . ProgressLocation . Notification ,
479481 cancellable : true ,
480482 title : 'Capturing workspace snapshot'
481- } , _ => {
482- return context . gitpod . server . takeSnapshot ( { workspaceId : context . info . getWorkspaceId ( ) /*, layoutData?*/ } ) ;
483+ } , async ( _ , cancelToken : CancellationToken ) => {
484+ snapshotId = await context . gitpod . server . takeSnapshot ( { workspaceId : context . info . getWorkspaceId ( ) /*, layoutData?*/ , dontWait : true } ) ;
485+
486+ while ( ! cancelToken . isCancellationRequested ) {
487+ try {
488+ await context . gitpod . server . waitForSnapshot ( snapshotId ) ;
489+ return ;
490+ } catch ( err ) {
491+ if ( err . code === ErrorCodes . SNAPSHOT_ERROR || err . code === ErrorCodes . NOT_FOUND ) {
492+ // this is indeed an error with snapshot creation itself, break here!
493+ throw err ;
494+ }
495+
496+ // other errors (like connection errors): retry
497+ await new Promise ( ( resolve ) => setTimeout ( resolve , 3000 ) ) ;
498+ }
499+ }
483500 } ) ;
501+ if ( ! snapshotId ) {
502+ throw new Error ( 'error taking snapshot' ) ;
503+ }
504+
484505 const hostname = context . info . getGitpodApi ( ) ! . getHost ( ) ;
485506 const uri = `https://${ hostname } #snapshot/${ snapshotId } ` ;
486507 const copyAction = await vscode . window . showInformationMessage ( `The current state is captured in a snapshot. Using [this link](${ uri } ) anybody can create their own copy of this workspace.` ,
0 commit comments