diff --git a/src/renderer/api/kube-api.ts b/src/renderer/api/kube-api.ts index c0b6f00884..56a0e18825 100644 --- a/src/renderer/api/kube-api.ts +++ b/src/renderer/api/kube-api.ts @@ -96,6 +96,7 @@ export function ensureObjectSelfLink(api: KubeApi, object: KubeJsonApiData) { type KubeApiWatchOptions = { namespace: string; callback?: (data: IKubeWatchEvent) => void; + abortController?: AbortController }; export class KubeApi { @@ -366,13 +367,31 @@ export class KubeApi { } watch(opts: KubeApiWatchOptions = { namespace: "" }): () => void { - const { namespace, callback } = opts; + if (!opts.abortController) { + opts.abortController = new AbortController(); + } + const { abortController, namespace, callback } = opts; const watchUrl = this.getWatchUrl(namespace); - const abortController = new AbortController(); const responsePromise = this.request.getReadableStream(watchUrl, null, { signal: abortController.signal }); let disposed = false; responsePromise.then((response) => { + if (!response.ok && !disposed) { + if (response.status === 410) { // resourceVersion has gone + setTimeout(() => { + this.refreshResourceVersion().then(() => { + this.watch({...opts, abortController}); + }); + }, 1000); + + } else if (response.status >= 500) { // k8s is having hard time + setTimeout(() => { + this.watch({...opts, abortController}); + }, 5000); + } + + return; + } const nodeStream = new ReadableWebToNodeStream(response.body); const stream = byline(nodeStream); @@ -392,13 +411,9 @@ export class KubeApi { stream.on("close", () => { setTimeout(() => { - if (!disposed) this.watch({namespace, callback}); + if (!disposed) this.watch({...opts, namespace, callback}); }, 1000); }); - - stream.on("error", (error) => { - console.error("stream error", error); - }); }, (error) => { if (error instanceof DOMException) return; // AbortController rejects, we can ignore it diff --git a/src/renderer/kube-object.store.ts b/src/renderer/kube-object.store.ts index d90de26e67..830cd7918f 100644 --- a/src/renderer/kube-object.store.ts +++ b/src/renderer/kube-object.store.ts @@ -267,6 +267,7 @@ export abstract class KubeObjectStore extends ItemSt } subscribe(apis = this.getSubscribeApis()) { + const abortController = new AbortController(); let disposers: {(): void}[] = []; const callback = (data: IKubeWatchEvent) => { @@ -275,13 +276,15 @@ export abstract class KubeObjectStore extends ItemSt if (this.context.cluster.isGlobalWatchEnabled) { disposers = apis.map(api => api.watch({ + abortController, namespace: "", - callback: (data) => callback(data) + callback: (data) => callback(data), })); } else { apis.map(api => { this.loadedNamespaces.forEach((namespace) => { disposers.push(api.watch({ + abortController, namespace, callback: (data) => callback(data) }));