@@ -10,7 +10,6 @@ import {
10
10
KernelError ,
11
11
ILSPDocumentConnectionManager ,
12
12
CodeEditorManager ,
13
- CodeEditorSettings ,
14
13
} from '@difizen/libro-jupyter' ;
15
14
import {
16
15
getOrigin ,
@@ -25,6 +24,7 @@ import {
25
24
} from '@difizen/mana-app' ;
26
25
import { l10n } from '@difizen/mana-l10n' ;
27
26
import { message } from 'antd' ;
27
+ import { isUndefined } from 'lodash-es' ;
28
28
import { forwardRef } from 'react' ;
29
29
30
30
import { Ribbon } from '@/components/ribbon' ;
@@ -36,15 +36,15 @@ import type { SecretNoteModel } from '../model';
36
36
37
37
const SecretNoteCodeCellComponent = forwardRef < HTMLDivElement > ( ( props , ref ) => {
38
38
const instance = useInject < SecretNoteCodeCellView > ( ViewInstance ) ;
39
- const { allExecutionParty , executionParty } = instance ;
39
+ const { partyList , parties } = instance ;
40
40
41
41
return (
42
42
< div className = { instance . className } ref = { ref } tabIndex = { 10 } onBlur = { instance . blur } >
43
43
< Ribbon
44
- items = { allExecutionParty }
45
- value = { executionParty }
44
+ items = { partyList . map ( ( name ) => ( { label : name , key : name } ) ) }
45
+ value = { parties }
46
46
onChange = { ( val ) => {
47
- instance . changeExecutionParty ( val ) ;
47
+ instance . onPartiesChange ( val ) ;
48
48
} }
49
49
>
50
50
< CellEditorMemo />
@@ -54,6 +54,8 @@ const SecretNoteCodeCellComponent = forwardRef<HTMLDivElement>((props, ref) => {
54
54
} ) ;
55
55
SecretNoteCodeCellComponent . displayName = 'SecretNoteCodeCellComponent' ;
56
56
57
+ let lastParties : string [ ] = [ ] ; // store last parties for new cell
58
+
57
59
@transient ( )
58
60
@view ( 'secretnote-code-cell-view' )
59
61
export class SecretNoteCodeCellView extends JupyterCodeCellView {
@@ -63,13 +65,10 @@ export class SecretNoteCodeCellView extends JupyterCodeCellView {
63
65
view = SecretNoteCodeCellComponent ;
64
66
65
67
@prop ( )
66
- executionParty : string [ ] = [ ] ;
68
+ parties : string [ ] = [ ] ;
67
69
68
- get allExecutionParty ( ) {
69
- return this . serverManager . servers . map ( ( server ) => ( {
70
- key : server . id ,
71
- label : server . name ,
72
- } ) ) ;
70
+ get partyList ( ) {
71
+ return this . serverManager . servers . map ( ( server ) => server . name ) ;
73
72
}
74
73
75
74
constructor (
@@ -80,89 +79,72 @@ export class SecretNoteCodeCellView extends JupyterCodeCellView {
80
79
@inject ( SecretNoteKernelManager ) kernelManager : SecretNoteKernelManager ,
81
80
@inject ( ILSPDocumentConnectionManager ) lsp : ILSPDocumentConnectionManager ,
82
81
@inject ( CodeEditorManager ) codeEditorManager : CodeEditorManager ,
83
- @inject ( CodeEditorSettings ) codeEditorSettings : CodeEditorSettings ,
84
82
) {
85
- super (
86
- options ,
87
- cellService ,
88
- viewManager ,
89
- lsp ,
90
- codeEditorManager ,
91
- codeEditorSettings ,
92
- ) ;
83
+ super ( options , cellService , viewManager , lsp , codeEditorManager ) ;
93
84
this . serverManager = serverManager ;
94
85
this . kernelManager = kernelManager ;
95
- this . executionParty =
96
- this . getExecutionParty ( ) || this . allExecutionParty . map ( ( item ) => item . key ) ;
86
+ this . parties = this . getInitializedParties ( ) ;
97
87
}
98
88
99
- async run ( ) {
89
+ getUsableConnections ( ) {
100
90
const libroModel = this . parent . model as SecretNoteModel ;
101
- const cellModel = this . model ;
102
91
103
92
if ( ! libroModel ) {
104
- return false ;
93
+ return [ ] ;
105
94
}
106
95
107
- let kernelConnections = getOrigin ( libroModel . kernelConnections ) ;
108
-
109
- // 没有可用的 Kernel 连接
110
- if ( kernelConnections . length === 0 ) {
111
- message . info ( l10n . t ( '没有可用的 Kernel 连接' ) ) ;
112
- return false ;
113
- }
96
+ const kernelConnections = getOrigin ( libroModel . kernelConnections ) ;
114
97
115
- kernelConnections = kernelConnections . filter ( ( connection ) => {
98
+ return kernelConnections . filter ( ( connection ) => {
99
+ if ( connection . isDisposed ) {
100
+ return false ;
101
+ }
116
102
const server = this . kernelManager . getServerByKernelConnection ( connection ) ;
117
103
return (
118
- server && server . status === 'running' && this . executionParty . includes ( server . id )
104
+ server && server . status === 'running' && this . parties . includes ( server . name )
119
105
) ;
120
106
} ) ;
121
- if ( kernelConnections . length === 0 ) {
122
- message . info ( l10n . t ( '请选择一个执行节点' ) ) ;
123
- return false ;
124
- }
125
- if ( kernelConnections . length !== this . executionParty . length ) {
126
- message . info ( l10n . t ( '有的 Kernel 连接不可用' ) ) ;
127
- return false ;
128
- }
107
+ }
129
108
130
- const hasDisposedConnection = kernelConnections . some ( ( item ) => {
131
- return item . isDisposed ;
132
- } ) ;
133
- if ( hasDisposedConnection ) {
134
- message . error ( l10n . t ( '有的 Kernel 连接已经被销毁' ) ) ;
109
+ async run ( ) {
110
+ const cellModel = this . model ;
111
+ const kernelConnections = this . getUsableConnections ( ) ;
112
+
113
+ if ( kernelConnections . length === 0 ) {
114
+ message . info ( l10n . t ( 'No available node to execute' ) ) ;
135
115
return false ;
136
116
}
137
117
138
118
this . clearExecution ( ) ;
139
- this . setExecutionStatus ( { executing : true } ) ;
140
- this . setExecutionTime ( { start : '' , end : '' , toExecute : new Date ( ) . toISOString ( ) } ) ;
141
- this . setExecutionParty ( ) ;
119
+ this . updateExecutionStatus ( { executing : true } ) ;
120
+ this . updateExecutionTime ( {
121
+ toExecute : new Date ( ) . toISOString ( ) ,
122
+ } ) ;
123
+ this . savePartiesToMeta ( ) ;
142
124
143
125
try {
144
126
const list : Promise < KernelMessage . IExecuteReplyMsg > [ ] = [ ] ;
145
127
for ( let i = 0 , len = kernelConnections . length ; i < len ; i += 1 ) {
146
128
const connection = kernelConnections [ i ] ;
147
-
148
- const future = connection . requestExecute ( {
149
- code : cellModel . value ,
150
- } ) ;
129
+ const future = connection . requestExecute (
130
+ {
131
+ code : cellModel . value ,
132
+ } ,
133
+ // Even after receiving a reply message, you can still receive other messages.
134
+ false ,
135
+ ) ;
151
136
152
137
future . onIOPub = (
153
138
msg : KernelMessage . IIOPubMessage < KernelMessage . IOPubMessageType > ,
154
139
) => {
140
+ if ( msg . header . msg_type === 'execute_input' ) {
141
+ this . updateExecutionStatus ( { kernelExecuting : true } ) ;
142
+ this . updateExecutionTime ( { start : msg . header . date } ) ;
143
+ }
155
144
cellModel . msgChangeEmitter . fire ( {
156
145
connection,
157
146
msg,
158
147
} ) ;
159
- if (
160
- cellModel . kernelExecuting === false &&
161
- msg . header . msg_type === 'execute_input'
162
- ) {
163
- this . setExecutionStatus ( { kernelExecuting : true } ) ;
164
- this . setExecutionTime ( { start : msg . header . date } ) ;
165
- }
166
148
} ;
167
149
168
150
future . onReply = ( msg : KernelMessage . IExecuteReplyMsg ) => {
@@ -176,8 +158,8 @@ export class SecretNoteCodeCellView extends JupyterCodeCellView {
176
158
}
177
159
178
160
const futureDoneList = await Promise . all ( list ) ;
179
- this . setExecutionStatus ( { executing : false , kernelExecuting : false } ) ;
180
- this . setExecutionTime ( this . parseMessageTime ( futureDoneList ) ) ;
161
+ this . updateExecutionStatus ( { executing : false , kernelExecuting : false } ) ;
162
+ this . updateExecutionTime ( this . parseMessageTime ( futureDoneList ) ) ;
181
163
182
164
const ok = futureDoneList . every ( ( msg ) => msg . content . status === 'ok' ) ;
183
165
if ( ok ) {
@@ -197,27 +179,27 @@ export class SecretNoteCodeCellView extends JupyterCodeCellView {
197
179
}
198
180
}
199
181
200
- setExecutionStatus ( status : { executing ?: boolean ; kernelExecuting ?: boolean } ) {
182
+ updateExecutionStatus ( status : { executing ?: boolean ; kernelExecuting ?: boolean } ) {
201
183
const { executing, kernelExecuting } = status ;
202
- if ( executing !== undefined ) {
184
+ if ( ! isUndefined ( executing ) ) {
203
185
this . model . executing = executing ;
204
186
}
205
- if ( kernelExecuting !== undefined ) {
187
+ if ( ! isUndefined ( kernelExecuting ) ) {
206
188
this . model . kernelExecuting = kernelExecuting ;
207
189
}
208
190
}
209
191
210
- setExecutionTime ( times : { start ?: string ; end ?: string ; toExecute ?: string } ) {
192
+ updateExecutionTime ( times : { start ?: string ; end ?: string ; toExecute ?: string } ) {
211
193
const meta = this . model . metadata . execution as ExecutionMeta ;
212
194
if ( meta ) {
213
195
const { start, end, toExecute } = times ;
214
- if ( start !== undefined ) {
196
+ if ( ! isUndefined ( start ) ) {
215
197
meta [ 'shell.execute_reply.started' ] = start ;
216
198
}
217
- if ( end !== undefined ) {
199
+ if ( ! isUndefined ( end ) ) {
218
200
meta [ 'shell.execute_reply.end' ] = end ;
219
201
}
220
- if ( toExecute !== undefined ) {
202
+ if ( ! isUndefined ( toExecute ) ) {
221
203
meta . to_execute = toExecute ;
222
204
}
223
205
}
@@ -240,29 +222,32 @@ export class SecretNoteCodeCellView extends JupyterCodeCellView {
240
222
return { start, end } ;
241
223
}
242
224
243
- changeExecutionParty ( party : string [ ] ) {
244
- this . executionParty = party ;
245
- this . setExecutionParty ( party ) ;
225
+ onPartiesChange ( parties : string [ ] ) {
226
+ this . parties = parties ;
227
+ this . savePartiesToMeta ( parties ) ;
228
+ lastParties = parties ;
246
229
}
247
230
248
- getExecutionParty ( ) {
231
+ getInitializedParties ( ) {
249
232
const execution = this . model . metadata . execution as ExecutionMeta ;
250
- if ( execution && execution . executionParty ) {
233
+ if ( execution && execution . parties ) {
251
234
try {
252
- const party : string [ ] = JSON . parse ( execution . executionParty as string ) ;
253
- return party . filter ( ( p ) =>
254
- this . allExecutionParty . some ( ( item ) => item . key === p ) ,
255
- ) ;
235
+ const parties : string [ ] = JSON . parse ( execution . parties as string ) ;
236
+ return parties . filter ( ( p ) => this . partyList . includes ( p ) ) ;
256
237
} catch ( e ) {
257
238
return [ ] ;
258
239
}
240
+ } else if ( lastParties . length > 0 ) {
241
+ // load parties from previous cell settings
242
+ return lastParties ;
259
243
}
244
+ return this . partyList ;
260
245
}
261
246
262
- setExecutionParty ( party : string [ ] = this . executionParty ) {
247
+ savePartiesToMeta ( parties : string [ ] = this . parties ) {
263
248
const execution = this . model . metadata . execution as ExecutionMeta ;
264
249
if ( execution ) {
265
- execution . executionParty = JSON . stringify ( party ) ;
250
+ execution . parties = JSON . stringify ( parties ) ;
266
251
}
267
252
}
268
253
}
0 commit comments