@@ -8,6 +8,7 @@ require('reflect-metadata');
8
8
import { GitpodClient , GitpodServer , GitpodServiceImpl , WorkspaceInstanceUpdateListener } from '@gitpod/gitpod-protocol/lib/gitpod-service' ;
9
9
import { JsonRpcProxyFactory } from '@gitpod/gitpod-protocol/lib/messaging/proxy-factory' ;
10
10
import { NavigatorContext , PullRequestContext , User } from '@gitpod/gitpod-protocol/lib/protocol' ;
11
+ import { ErrorCodes } from '@gitpod/gitpod-protocol/lib/messaging/error' ;
11
12
import { GitpodHostUrl } from '@gitpod/gitpod-protocol/lib/util/gitpod-host-url' ;
12
13
import { ControlServiceClient } from '@gitpod/supervisor-api-grpc/lib/control_grpc_pb' ;
13
14
import { InfoServiceClient } from '@gitpod/supervisor-api-grpc/lib/info_grpc_pb' ;
@@ -29,7 +30,7 @@ import ReconnectingWebSocket from 'reconnecting-websocket';
29
30
import { URL } from 'url' ;
30
31
import * as util from 'util' ;
31
32
import * 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' ;
33
34
import WebSocket = require( 'ws' ) ;
34
35
import { BaseGitpodAnalyticsEventPropeties , GitpodAnalyticsEvent } from './analytics' ;
35
36
import * as uuid from 'uuid' ;
@@ -68,7 +69,7 @@ export class SupervisorConnection {
68
69
}
69
70
}
70
71
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' ] ;
72
73
type Union < Tuple extends any [ ] , Union = never > = Tuple [ number ] | Union ;
73
74
export type GitpodConnection = Omit < GitpodServiceImpl < GitpodClient , GitpodServer > , 'server' > & {
74
75
server : Pick < GitpodServer , Union < UsedGitpodFunction > >
@@ -237,7 +238,7 @@ export async function createGitpodExtensionContext(context: vscode.ExtensionCont
237
238
const gitpodApi = workspaceInfo . getGitpodApi ( ) ! ;
238
239
239
240
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' ] ;
241
242
const gitpodService : GitpodConnection = new GitpodServiceImpl < GitpodClient , GitpodServer > ( factory . createProxy ( ) ) as any ;
242
243
const gitpodScopes = new Set < string > ( [
243
244
'resource:workspace::' + workspaceId + '::get/update' ,
@@ -474,13 +475,33 @@ export async function registerWorkspaceCommands(context: GitpodExtensionContext)
474
475
properties : { action : 'snapshot' }
475
476
} ) ;
476
477
try {
477
- const snapshotId = await vscode . window . withProgress ( {
478
+ let snapshotId : string | undefined = undefined ;
479
+ await vscode . window . withProgress ( {
478
480
location : vscode . ProgressLocation . Notification ,
479
481
cancellable : true ,
480
482
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
+ }
483
500
} ) ;
501
+ if ( ! snapshotId ) {
502
+ throw new Error ( 'error taking snapshot' ) ;
503
+ }
504
+
484
505
const hostname = context . info . getGitpodApi ( ) ! . getHost ( ) ;
485
506
const uri = `https://${ hostname } #snapshot/${ snapshotId } ` ;
486
507
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