Skip to content

Commit ade9094

Browse files
committed
Fixed disconnection events handling
Signed-off-by: Seb Julliand <sebjulliand@gmail.com>
1 parent a4af0f2 commit ade9094

File tree

2 files changed

+51
-56
lines changed

2 files changed

+51
-56
lines changed

src/Instance.ts

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { EventEmitter } from "stream";
22
import * as vscode from "vscode";
33
import { ILELibrarySettings } from "./api/CompileTools";
4-
import IBMi, { ConnectionResult } from "./api/IBMi";
4+
import IBMi, { ConnectionResult, DisconnectedCallback } from "./api/IBMi";
55
import { BaseStorage } from "./api/configuration/storage/BaseStorage";
66
import { CodeForIStorage } from "./api/configuration/storage/CodeForIStorage";
77
import { ConnectionStorage } from "./api/configuration/storage/ConnectionStorage";
@@ -79,27 +79,32 @@ export default class Instance {
7979

8080
let result: ConnectionResult;
8181

82-
const timeoutHandler = async (conn: IBMi) => {
83-
if (conn) {
84-
const choice = await vscode.window.showWarningMessage(`Connection lost`, {
85-
modal: true,
86-
detail: `Connection to ${conn.currentConnectionName} has dropped. Would you like to reconnect?`
87-
}, `Yes`, `No, get logs`);
88-
89-
let reconnect = choice === `Yes`;
90-
let collectLogs = choice === `No, get logs`;
91-
92-
if (collectLogs) {
93-
const logs = this.output.content;
94-
vscode.workspace.openTextDocument({ content: logs, language: `plaintext` }).then(doc => {
95-
vscode.window.showTextDocument(doc);
96-
});
97-
}
82+
const onDisconnected: DisconnectedCallback = async (connection, error) => {
83+
if (connection.connectionSuccessful) {
84+
this.setConnection();
85+
this.fire(`disconnected`);
9886

99-
this.disconnect();
87+
if (error) {
88+
const choice = await vscode.window.showWarningMessage(`Connection lost: ${error.description || error.message || error.level}`, {
89+
modal: true,
90+
detail: `Connection to ${connection.currentConnectionName} has dropped. Would you like to reconnect?`
91+
}, `Yes`, `No, get logs`);
10092

101-
if (reconnect) {
102-
await this.connect({ ...options, reconnecting: true });
93+
const reconnect = choice === `Yes`;
94+
const collectLogs = choice === `No, get logs`;
95+
96+
if (collectLogs) {
97+
const logs = this.output.content;
98+
vscode.workspace.openTextDocument({ content: logs, language: `plaintext` }).then(doc => {
99+
vscode.window.showTextDocument(doc);
100+
});
101+
}
102+
103+
this.disconnect();
104+
105+
if (reconnect) {
106+
await this.connect({ ...options, reconnecting: true });
107+
}
103108
}
104109
}
105110
};
@@ -119,8 +124,8 @@ export default class Instance {
119124
options.data,
120125
{
121126
callbacks: {
122-
timeoutCallback: timeoutHandler,
123-
onConnectedOperations: options.onConnectedOperations || [],
127+
onDisconnected,
128+
onConnectedOperations: options.onConnectedOperations,
124129
uiErrorHandler: handleConnectionResults,
125130
progress: (message) => { p.report(message) },
126131
message: messageCallback,
@@ -183,11 +188,6 @@ export default class Instance {
183188
}
184189

185190
if (connection) {
186-
connection.setDisconnectedCallback(async () => {
187-
this.setConnection();
188-
this.fire(`disconnected`);
189-
});
190-
191191
this.connection = connection;
192192
this.storage.setConnectionName(connection.currentConnectionName);
193193
await IBMi.GlobalStorage.setLastConnection(connection.currentConnectionName);

src/api/IBMi.ts

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ export interface ConnectionResult {
2929
errorCodes?: ConnectionErrorCode[]
3030
}
3131

32+
export type SSHError = {
33+
level: 'client-socket' | 'client-ssh'
34+
message?: string
35+
description?: string
36+
}
37+
38+
export type DisconnectedCallback = (conn: IBMi, error?: SSHError) => Promise<void>;
39+
3240
const remoteApps = [ // All names MUST also be defined as key in 'remoteFeatures' below!!
3341
{
3442
path: `/usr/bin/`,
@@ -45,11 +53,9 @@ const remoteApps = [ // All names MUST also be defined as key in 'remoteFeatures
4553
}
4654
];
4755

48-
type DisconnectCallback = (conn: IBMi) => Promise<void>;
49-
5056
interface ConnectionCallbacks {
5157
onConnectedOperations?: Function[],
52-
timeoutCallback?: (conn: IBMi) => Promise<void>,
58+
onDisconnected?: DisconnectedCallback,
5359
uiErrorHandler: (connection: IBMi, error: ConnectionErrorCode, data?: any) => Promise<boolean>,
5460
progress: (detail: { message: string }) => void,
5561
message: (type: ConnectionMessageType, message: string) => void,
@@ -116,6 +122,8 @@ export default class IBMi {
116122
private currentAsp: string | undefined;
117123
private libraryAsps = new Map<string, number>();
118124

125+
connectionSuccessful = false;
126+
119127
/**
120128
* @deprecated Will be replaced with {@link IBMi.getAllIAsps} in v3.0.0
121129
*/
@@ -147,15 +155,6 @@ export default class IBMi {
147155
process.stdout.write(text);
148156
};
149157

150-
private disconnectedCallback: (DisconnectCallback) | undefined;
151-
152-
/**
153-
* Will only be called once per connection.
154-
*/
155-
setDisconnectedCallback(callback: DisconnectCallback) {
156-
this.disconnectedCallback = callback;
157-
}
158-
159158
/**
160159
* getConfigFile can return pre-defined configuration files,
161160
* but can lazy load new configuration files as well.
@@ -336,19 +335,17 @@ export default class IBMi {
336335
};
337336
}
338337

339-
if (callbacks.timeoutCallback) {
340-
const timeoutCallbackWrapper = () => {
341-
// Don't call the callback function if it was based on a user cancellation request.
342-
if (!wasCancelled) {
343-
callbacks.timeoutCallback!(this);
344-
}
338+
// Trigger callbacks unless the connection is cancelled
339+
const callbackWrapper = (error?: SSHError) => {
340+
if (!wasCancelled) {
341+
callbacks.onDisconnected?.(this, error);
345342
}
343+
};
346344

347-
// Register handlers after we might have to abort due to bad configuration.
348-
this.client.connection!.once(`timeout`, timeoutCallbackWrapper);
349-
this.client.connection!.once(`end`, timeoutCallbackWrapper);
350-
this.client.connection!.once(`error`, timeoutCallbackWrapper);
351-
}
345+
//end: disconnected by user
346+
this.client.connection.once(`end`, callbackWrapper);
347+
//error: connection dropped for some reason (details given in the SSHError type)
348+
this.client.connection.once(`error`, callbackWrapper);
352349

353350
callbacks.progress({
354351
message: `Checking home directory.`
@@ -956,8 +953,7 @@ export default class IBMi {
956953
}
957954

958955
if (!options.reconnecting) {
959-
const delayedOperations: Function[] = callbacks.onConnectedOperations ? [...callbacks.onConnectedOperations] : [];
960-
for (const operation of delayedOperations) {
956+
for (const operation of callbacks.onConnectedOperations || []) {
961957
await operation();
962958
}
963959
}
@@ -977,6 +973,8 @@ export default class IBMi {
977973
maximumArgsLength: this.maximumArgsLength
978974
});
979975

976+
this.connectionSuccessful = true;
977+
980978
return {
981979
success: true
982980
};
@@ -1172,11 +1170,8 @@ export default class IBMi {
11721170
}
11731171

11741172
if (this.client) {
1173+
this.client.dispose();
11751174
this.client = undefined;
1176-
1177-
if (failedToConnect === false && this.disconnectedCallback) {
1178-
this.disconnectedCallback(this);
1179-
}
11801175
}
11811176
}
11821177

0 commit comments

Comments
 (0)