@@ -38,7 +38,7 @@ import {
3838} from '../colab/headers' ;
3939import { log } from '../common/logging' ;
4040import { telemetry } from '../telemetry' ;
41- import { CommandSource } from '../telemetry/api' ;
41+ import { AssignmentOutcome , CommandSource } from '../telemetry/api' ;
4242import { ProxiedJupyterClient } from './client' ;
4343import { colabProxyWebSocket } from './colab-proxy-websocket' ;
4444import {
@@ -327,60 +327,76 @@ export class AssignmentManager implements Disposable {
327327 this . guardDisposed ( ) ;
328328 const id = randomUUID ( ) ;
329329 const { label, variant, accelerator, shape, version } = descriptor ;
330- let assignment : Assignment ;
330+ let outcome = AssignmentOutcome . ASSIGNMENT_OUTCOME_UNSPECIFIED ;
331+ let hadFallback = false ;
331332 try {
332- if ( isColabServerDescriptorWithAccelerator ( descriptor ) ) {
333- assignment = await this . assignWithFallback (
334- id ,
335- descriptor ,
336- /* fallbacks= */ undefined ,
337- signal ,
338- ) ;
339- } else {
340- ( { assignment } = await this . client . assign (
341- id ,
342- { variant, accelerator, shape, version } ,
343- signal ,
344- ) ) ;
345- }
346- } catch ( error ) {
347- log . trace ( `Failed assigning server ${ id } ` , error ) ;
348- if ( error instanceof AllAcceleratorsUnavailableError ) {
349- void this . notifyAllAcceleratorsUnavailable ( error ) ;
350- }
351- // TODO: Consider listing assignments to check if there are too many
352- // before the user goes through the assignment flow. This handling logic
353- // would still be needed for the rare race condition where an assignment
354- // is made (e.g. in Colab web) during the extension assignment flow.
355- if ( error instanceof TooManyAssignmentsError ) {
356- void this . notifyMaxAssignmentsExceeded ( ) ;
357- }
358- if ( error instanceof InsufficientQuotaError ) {
359- void this . notifyInsufficientQuota ( error ) ;
360- }
361- if ( error instanceof DenylistedError ) {
362- this . notifyBanned ( error ) ;
333+ let assignment : Assignment ;
334+ try {
335+ if ( isColabServerDescriptorWithAccelerator ( descriptor ) ) {
336+ assignment = await this . assignWithFallback (
337+ id ,
338+ descriptor ,
339+ /* fallbacks= */ undefined ,
340+ signal ,
341+ ) ;
342+ hadFallback = assignment . accelerator !== descriptor . accelerator ;
343+ } else {
344+ ( { assignment } = await this . client . assign (
345+ id ,
346+ { variant, accelerator, shape, version } ,
347+ signal ,
348+ ) ) ;
349+ }
350+ } catch ( error ) {
351+ log . trace ( `Failed assigning server ${ id } ` , error ) ;
352+ outcome = errorToAssignmentOutcome ( error ) ;
353+ if ( error instanceof AllAcceleratorsUnavailableError ) {
354+ hadFallback = error . attempted . length > 1 ;
355+ void this . notifyAllAcceleratorsUnavailable ( error ) ;
356+ }
357+ // TODO: Consider listing assignments to check if there are too many
358+ // before the user goes through the assignment flow. This handling logic
359+ // would still be needed for the rare race condition where an assignment
360+ // is made (e.g. in Colab web) during the extension assignment flow.
361+ if ( error instanceof TooManyAssignmentsError ) {
362+ void this . notifyMaxAssignmentsExceeded ( ) ;
363+ }
364+ if ( error instanceof InsufficientQuotaError ) {
365+ void this . notifyInsufficientQuota ( error ) ;
366+ }
367+ if ( error instanceof DenylistedError ) {
368+ this . notifyBanned ( error ) ;
369+ }
370+ throw error ;
363371 }
364- throw error ;
372+ const server = this . toAssignedServer (
373+ {
374+ id,
375+ label,
376+ variant : assignment . variant ,
377+ accelerator : assignment . accelerator ,
378+ } ,
379+ assignment . endpoint ,
380+ assignment . runtimeProxyInfo ,
381+ new Date ( ) ,
382+ ) ;
383+ await this . storage . store ( [ server ] ) ;
384+ this . assignmentChange . fire ( {
385+ added : [ server ] ,
386+ removed : [ ] ,
387+ changed : [ ] ,
388+ } ) ;
389+ outcome = AssignmentOutcome . ASSIGNMENT_OUTCOME_SUCCEEDED ;
390+ return server ;
391+ } finally {
392+ telemetry . logAssignServer ( outcome , {
393+ variant,
394+ accelerator : accelerator ?? '' ,
395+ shape : shape !== undefined ? Shape [ shape ] : '' ,
396+ version : version ?? '' ,
397+ hadFallback,
398+ } ) ;
365399 }
366- const server = this . toAssignedServer (
367- {
368- id,
369- label,
370- variant : assignment . variant ,
371- accelerator : assignment . accelerator ,
372- } ,
373- assignment . endpoint ,
374- assignment . runtimeProxyInfo ,
375- new Date ( ) ,
376- ) ;
377- await this . storage . store ( [ server ] ) ;
378- this . assignmentChange . fire ( {
379- added : [ server ] ,
380- removed : [ ] ,
381- changed : [ ] ,
382- } ) ;
383- return server ;
384400 }
385401
386402 /**
@@ -854,3 +870,22 @@ function isColabServerDescriptorWithAccelerator(
854870) : descriptor is ColabServerDescriptorWithAccelerator {
855871 return ! ! descriptor . accelerator ;
856872}
873+
874+ function errorToAssignmentOutcome ( error : unknown ) : AssignmentOutcome {
875+ if ( error instanceof AllAcceleratorsUnavailableError ) {
876+ return AssignmentOutcome . ASSIGNMENT_OUTCOME_ALL_ACCELERATORS_UNAVAILABLE ;
877+ }
878+ if ( error instanceof AcceleratorUnavailableError ) {
879+ return AssignmentOutcome . ASSIGNMENT_OUTCOME_ACCELERATOR_UNAVAILABLE ;
880+ }
881+ if ( error instanceof TooManyAssignmentsError ) {
882+ return AssignmentOutcome . ASSIGNMENT_OUTCOME_TOO_MANY_ASSIGNMENTS ;
883+ }
884+ if ( error instanceof InsufficientQuotaError ) {
885+ return AssignmentOutcome . ASSIGNMENT_OUTCOME_INSUFFICIENT_QUOTA ;
886+ }
887+ if ( error instanceof DenylistedError ) {
888+ return AssignmentOutcome . ASSIGNMENT_OUTCOME_DENYLISTED ;
889+ }
890+ return AssignmentOutcome . ASSIGNMENT_OUTCOME_OTHER_FAILURE ;
891+ }
0 commit comments