mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
auto-reconnect on online/offline status change, interval connection check
Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
parent
632e77b263
commit
14a0c9cdca
@ -40,15 +40,34 @@ export class KubeWatchApi {
|
|||||||
private namespaceStore: NamespaceStore;
|
private namespaceStore: NamespaceStore;
|
||||||
|
|
||||||
private requestId = 0;
|
private requestId = 0;
|
||||||
|
private isConnected = false;
|
||||||
private reader: ReadableStreamReader<string>;
|
private reader: ReadableStreamReader<string>;
|
||||||
private subscribers = observable.map<KubeApi, number>();
|
private subscribers = observable.map<KubeApi, number>();
|
||||||
private splitter = "\n";
|
|
||||||
private reconnectTimeoutMs = 5000;
|
|
||||||
private maxReconnectsOnError = 10;
|
|
||||||
|
|
||||||
// events
|
// events
|
||||||
public onMessage = new EventEmitter<[IKubeWatchMessage]>();
|
public onMessage = new EventEmitter<[IKubeWatchMessage]>();
|
||||||
|
|
||||||
|
@computed get isActive(): boolean {
|
||||||
|
return this.apis.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get apis(): string[] {
|
||||||
|
const { cluster, namespaceStore } = this;
|
||||||
|
const activeApis = Array.from(this.subscribers.keys());
|
||||||
|
|
||||||
|
return activeApis.map(api => {
|
||||||
|
if (!cluster.isAllowedResource(api.kind)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (api.isNamespaced) {
|
||||||
|
return namespaceStore.getContextNamespaces().map(namespace => api.getWatchUrl(namespace));
|
||||||
|
} else {
|
||||||
|
return api.getWatchUrl();
|
||||||
|
}
|
||||||
|
}).flat();
|
||||||
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
@ -67,27 +86,14 @@ export class KubeWatchApi {
|
|||||||
private bindAutoConnect() {
|
private bindAutoConnect() {
|
||||||
const connect = debounce(() => this.connect(), 1000);
|
const connect = debounce(() => this.connect(), 1000);
|
||||||
|
|
||||||
return reaction(() => this.activeApis, connect, {
|
reaction(() => this.apis, connect, {
|
||||||
fireImmediately: true,
|
fireImmediately: true,
|
||||||
equals: comparer.structural,
|
equals: comparer.structural,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
@computed get activeApis(): string[] {
|
window.addEventListener("online", () => this.connect());
|
||||||
const { cluster, namespaceStore } = this;
|
window.addEventListener("offline", () => this.disconnect());
|
||||||
const activeApis = Array.from(this.subscribers.keys());
|
setInterval(() => this.connectionCheck(), 30000);
|
||||||
|
|
||||||
return activeApis.map(api => {
|
|
||||||
if (!cluster.isAllowedResource(api.kind)) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (api.isNamespaced) {
|
|
||||||
return namespaceStore.getContextNamespaces().map(namespace => api.getWatchUrl(namespace));
|
|
||||||
} else {
|
|
||||||
return api.getWatchUrl();
|
|
||||||
}
|
|
||||||
}).flat();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getSubscribersCount(api: KubeApi) {
|
getSubscribersCount(api: KubeApi) {
|
||||||
@ -149,10 +155,18 @@ export class KubeWatchApi {
|
|||||||
return unsubscribe;
|
return unsubscribe;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async connect(apis = this.activeApis) {
|
protected connectionCheck() {
|
||||||
|
if (this.isConnected) return;
|
||||||
|
|
||||||
|
return this.connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async connect(apis = this.apis) {
|
||||||
this.disconnect(); // close active connections first
|
this.disconnect(); // close active connections first
|
||||||
|
|
||||||
if (!apis.length) {
|
if (!navigator.onLine || !apis.length) {
|
||||||
|
this.isConnected = false;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,6 +199,7 @@ export class KubeWatchApi {
|
|||||||
const stream = request.body.pipeThrough(new TextDecoderStream());
|
const stream = request.body.pipeThrough(new TextDecoderStream());
|
||||||
const reader = stream.getReader();
|
const reader = stream.getReader();
|
||||||
|
|
||||||
|
this.isConnected = true;
|
||||||
this.reader = reader;
|
this.reader = reader;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -192,18 +207,21 @@ export class KubeWatchApi {
|
|||||||
|
|
||||||
if (done) break; // exit
|
if (done) break; // exit
|
||||||
|
|
||||||
const events = (jsonBuffer + value).split(this.splitter);
|
const events = (jsonBuffer + value).split("\n");
|
||||||
|
|
||||||
jsonBuffer = this.processBuffer(events);
|
jsonBuffer = this.processBuffer(events);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.log({ message: error });
|
this.log({ message: error });
|
||||||
|
} finally {
|
||||||
|
this.isConnected = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected disconnect() {
|
protected disconnect() {
|
||||||
this.reader?.cancel();
|
this.reader?.cancel();
|
||||||
this.reader = null;
|
this.reader = null;
|
||||||
|
this.isConnected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// process received stream events, returns unprocessed buffer chunk if any
|
// process received stream events, returns unprocessed buffer chunk if any
|
||||||
@ -272,14 +290,12 @@ export class KubeWatchApi {
|
|||||||
this.connect();
|
this.connect();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.log({
|
this.log({
|
||||||
message: new Error("Failed to reconnect on stream end"),
|
message: new Error(`Failed to connect on single stream end: ${error}`),
|
||||||
meta: { error, event },
|
meta: { event, error },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.subscribers.size > 0) {
|
if (this.isActive) {
|
||||||
setTimeout(() => {
|
setTimeout(() => this.onServerStreamEnd(event), 1000);
|
||||||
this.onServerStreamEnd(event);
|
|
||||||
}, 1000);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user