File tree Expand file tree Collapse file tree 5 files changed +117
-6
lines changed
databricks-sdk-js/src/services Expand file tree Collapse file tree 5 files changed +117
-6
lines changed Original file line number Diff line number Diff line change @@ -101,4 +101,61 @@ describe(__filename, function () {
101101 await workspaceService . delete ( { path : jobPath } ) ;
102102 }
103103 } ) ;
104+
105+ it ( "should run a broken notebook job" , async ( ) => {
106+ const cluster = await Cluster . fromClusterId (
107+ integSetup . client ,
108+ integSetup . cluster . id
109+ ) ;
110+
111+ const jobPath = `/tmp/sdk-js-integ-${ integSetup . testRunId } .py` ;
112+ const workspaceService = new WorkspaceService ( integSetup . client ) ;
113+
114+ await workspaceService . mkdirs ( { path : "/tmp" } ) ;
115+
116+ await workspaceService . import ( {
117+ path : jobPath ,
118+ format : "SOURCE" ,
119+ language : "PYTHON" ,
120+ content : Buffer . from (
121+ `# Databricks notebook source
122+ # COMMAND ----------
123+
124+ pr int("Cell 1")
125+
126+ # COMMAND ----------
127+
128+ print("Cell 2")`
129+ ) . toString ( "base64" ) ,
130+ overwrite : true ,
131+ } ) ;
132+
133+ try {
134+ const progress : Array < WorkflowRun > = [ ] ;
135+ const output = await cluster . runNotebookAndWait ( {
136+ path : `${ jobPath } ` ,
137+ onProgress : (
138+ _state : jobs . RunLifeCycleState ,
139+ run : WorkflowRun
140+ ) => {
141+ progress . push ( run ) ;
142+ } ,
143+ } ) ;
144+
145+ assert ( progress . length > 1 ) ;
146+ assert . equal (
147+ progress [ progress . length - 1 ] . lifeCycleState ,
148+ "INTERNAL_ERROR"
149+ ) ;
150+
151+ assert (
152+ output . views &&
153+ output . views . length > 0 &&
154+ output . views [ 0 ] . content
155+ ) ;
156+ assert ( output . views [ 0 ] . content . startsWith ( "<!DOCTYPE html>" ) ) ;
157+ } finally {
158+ await workspaceService . delete ( { path : jobPath } ) ;
159+ }
160+ } ) ;
104161} ) ;
Original file line number Diff line number Diff line change @@ -62,7 +62,10 @@ export class WorkflowRun {
6262
6363 async export ( task ?: RunTask ) : Promise < ExportRunOutput > {
6464 task = task || this . tasks ! [ 0 ] ;
65- if ( this . lifeCycleState !== "TERMINATED" ) {
65+ if (
66+ this . lifeCycleState !== "TERMINATED" &&
67+ this . lifeCycleState !== "INTERNAL_ERROR"
68+ ) {
6669 throw new Error ( "Run is not terminated" ) ;
6770 }
6871 if ( ! this . tasks || ! this . tasks . length ) {
Original file line number Diff line number Diff line change @@ -64,11 +64,30 @@ export class WorkflowOutputPanel {
6464 } ) ;
6565 }
6666
67+ private getStateString ( runState : jobs . RunLifeCycleState ) : string {
68+ switch ( runState ) {
69+ case "PENDING" :
70+ return "Pending" ;
71+ case "RUNNING" :
72+ return "Running" ;
73+ case "TERMINATED" :
74+ return "Terminated" ;
75+ case "SKIPPED" :
76+ return "Skipped" ;
77+ case "INTERNAL_ERROR" :
78+ return "Failed" ;
79+ default :
80+ return "Unknown" ;
81+ }
82+ }
83+
6784 async updateState (
6885 cluster : Cluster ,
69- state : jobs . RunLifeCycleState ,
86+ runState : jobs . RunLifeCycleState ,
7087 run : WorkflowRun
7188 ) {
89+ const state = this . getStateString ( runState ) ;
90+
7291 this . panel . webview . postMessage ( {
7392 type : "status" ,
7493 state,
Original file line number Diff line number Diff line change @@ -22,6 +22,7 @@ import {WorkflowOutputPanel} from "./WorkflowOutputPanel";
2222
2323export class WorkflowRunner implements Disposable {
2424 private panels = new Map < string , WorkflowOutputPanel > ( ) ;
25+ private disposables = new Array < Disposable > ( ) ;
2526
2627 constructor (
2728 private context : ExtensionContext ,
@@ -32,6 +33,7 @@ export class WorkflowRunner implements Disposable {
3233 for ( const panel of this . panels . values ( ) ) {
3334 panel . dispose ( ) ;
3435 }
36+ this . disposables . forEach ( ( d ) => d . dispose ( ) ) ;
3537 }
3638
3739 private async getPanelForUri ( uri : Uri ) {
@@ -54,6 +56,9 @@ export class WorkflowRunner implements Disposable {
5456 ) ,
5557 this . context . extensionUri
5658 ) ;
59+ this . disposables . push (
60+ panel . onDidDispose ( ( ) => this . panels . delete ( key ) )
61+ ) ;
5762 this . panels . set ( key , panel ) ;
5863 }
5964
Original file line number Diff line number Diff line change 9393 display : none;
9494 }
9595
96+ .alert-error .error-icon {
97+ display : inline-block;
98+ padding : 0 8px ;
99+ }
100+
96101 .alert-error {
102+ display : flex;
97103 padding : 8px ;
98104 margin : 8px ;
99105 color : rgb (200 , 45 , 76 );
117123 }
118124
119125 .output .error # error {
120- display : block ;
126+ display : flex ;
121127 }
122128
123129 .details {
139145 < iframe id ="frame "> </ iframe >
140146 < pre id ="stdout "> </ pre >
141147 < div class ="alert-error " id ="error ">
142- < b id ="error-description "> </ b >
143- < pre id ="error-stack "> </ pre >
148+ < span class ="error-icon ">
149+ < svg
150+ width ="1em "
151+ height ="1em "
152+ viewBox ="0 0 24 24 "
153+ fill ="none "
154+ xmlns ="http://www.w3.org/2000/svg "
155+ aria-hidden ="true "
156+ focusable ="false "
157+ class =""
158+ >
159+ < path
160+ fill-rule ="evenodd "
161+ clip-rule ="evenodd "
162+ d ="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 11c-.55 0-1-.45-1-1V8c0-.55.45-1 1-1s1 .45 1 1v4c0 .55-.45 1-1 1zm-1 2v2h2v-2h-2z "
163+ fill ="currentColor "
164+ > </ path >
165+ </ svg >
166+ </ span >
167+ < div >
168+ < b id ="error-description "> </ b >
169+ < pre id ="error-stack "> </ pre >
170+ </ div >
144171 </ div >
145172 </ div >
146173 < div class ="details ">
174201 </ li >
175202 < li >
176203 < span class ="label "> Status:</ span >
177- < span class ="value " id ="run-status "> SYNCING </ span >
204+ < span class ="value " id ="run-status "> Synchronizing </ span >
178205 </ li >
179206 </ ul >
180207 </ div >
You can’t perform that action at this time.
0 commit comments