mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
workaround for browser connection limits
Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
parent
73195c2f14
commit
c134d322a9
@ -194,7 +194,8 @@ export class LensProxy {
|
|||||||
|
|
||||||
if (proxyTarget) {
|
if (proxyTarget) {
|
||||||
// allow to fetch apis in "clusterId.localhost:port" from "localhost:port"
|
// allow to fetch apis in "clusterId.localhost:port" from "localhost:port"
|
||||||
res.setHeader("Access-Control-Allow-Origin", this.origin);
|
// this should be safe because we have already validated cluster uuid
|
||||||
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
|
||||||
return proxy.web(req, res, proxyTarget);
|
return proxy.web(req, res, proxyTarget);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,17 +55,28 @@ export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
|
|||||||
return this.request<T>(path, params, { ...reqInit, method: "get" });
|
return this.request<T>(path, params, { ...reqInit, method: "get" });
|
||||||
}
|
}
|
||||||
|
|
||||||
getReadableStream(path: string, params?: P, init: RequestInit = {}): Promise<Response> {
|
getResponse(reqUrl: string, params?: P, init: RequestInit = { }): Promise<Response> {
|
||||||
let reqUrl = this.config.apiBase + path;
|
|
||||||
const reqInit: RequestInit = { ...init };
|
const reqInit: RequestInit = { ...init };
|
||||||
const { query } = params || {} as P;
|
const { query } = params || {} as P;
|
||||||
|
|
||||||
|
if (!reqInit.method) {
|
||||||
|
reqInit.method = "get";
|
||||||
|
}
|
||||||
|
|
||||||
if (query) {
|
if (query) {
|
||||||
const queryString = stringify(query);
|
const queryString = stringify(query);
|
||||||
|
|
||||||
reqUrl += (reqUrl.includes("?") ? "&" : "?") + queryString;
|
reqUrl += (reqUrl.includes("?") ? "&" : "?") + queryString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const infoLog: JsonApiLog = {
|
||||||
|
method: `${reqInit.method.toUpperCase()} (stream)`,
|
||||||
|
reqUrl,
|
||||||
|
reqInit,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.writeLog({ ...infoLog });
|
||||||
|
|
||||||
return fetch(reqUrl, reqInit);
|
return fetch(reqUrl, reqInit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -371,12 +371,15 @@ export class KubeApi<T extends KubeObject = any> {
|
|||||||
opts.abortController = new AbortController();
|
opts.abortController = new AbortController();
|
||||||
}
|
}
|
||||||
const { abortController, namespace, callback } = opts;
|
const { abortController, namespace, callback } = opts;
|
||||||
const watchUrl = this.getWatchUrl(namespace);
|
|
||||||
const responsePromise = this.request.getReadableStream(watchUrl, null, { signal: abortController.signal });
|
// FIXME
|
||||||
let disposed = false;
|
const watchUrl = `http://${this.kind}-watch.${window.location.host}${apiKubePrefix}${this.getWatchUrl(namespace)}`;
|
||||||
|
const responsePromise = this.request.getResponse(watchUrl, null, {
|
||||||
|
signal: abortController.signal
|
||||||
|
});
|
||||||
|
|
||||||
responsePromise.then((response) => {
|
responsePromise.then((response) => {
|
||||||
if (!response.ok && !disposed) {
|
if (!response.ok && !abortController.signal.aborted) {
|
||||||
if (response.status === 410) { // resourceVersion has gone
|
if (response.status === 410) { // resourceVersion has gone
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.refreshResourceVersion().then(() => {
|
this.refreshResourceVersion().then(() => {
|
||||||
@ -399,8 +402,6 @@ export class KubeApi<T extends KubeObject = any> {
|
|||||||
try {
|
try {
|
||||||
const data: IKubeWatchEvent = JSON.parse(line);
|
const data: IKubeWatchEvent = JSON.parse(line);
|
||||||
|
|
||||||
console.log("data", data);
|
|
||||||
|
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(data);
|
callback(data);
|
||||||
}
|
}
|
||||||
@ -411,7 +412,7 @@ export class KubeApi<T extends KubeObject = any> {
|
|||||||
|
|
||||||
stream.on("close", () => {
|
stream.on("close", () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (!disposed) this.watch({...opts, namespace, callback});
|
if (!abortController.signal.aborted) this.watch({...opts, namespace, callback});
|
||||||
}, 1000);
|
}, 1000);
|
||||||
});
|
});
|
||||||
}, (error) => {
|
}, (error) => {
|
||||||
@ -423,7 +424,6 @@ export class KubeApi<T extends KubeObject = any> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const disposer = () => {
|
const disposer = () => {
|
||||||
disposed = true;
|
|
||||||
abortController.abort();
|
abortController.abort();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import { MenuItem } from "../menu";
|
|||||||
import { Checkbox } from "../checkbox";
|
import { Checkbox } from "../checkbox";
|
||||||
import { userStore } from "../../../common/user-store";
|
import { userStore } from "../../../common/user-store";
|
||||||
import { namespaceStore } from "../+namespaces/namespace.store";
|
import { namespaceStore } from "../+namespaces/namespace.store";
|
||||||
|
import { Icon } from "../icon";
|
||||||
|
|
||||||
// todo: refactor, split to small re-usable components
|
// todo: refactor, split to small re-usable components
|
||||||
|
|
||||||
@ -341,16 +342,17 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
|
|||||||
const allItemsCount = this.props.store.getTotalCount();
|
const allItemsCount = this.props.store.getTotalCount();
|
||||||
const itemsCount = items.length;
|
const itemsCount = items.length;
|
||||||
const isFiltered = isReady && filters.length > 0;
|
const isFiltered = isReady && filters.length > 0;
|
||||||
|
const RefreshIcon = <Icon material="update" small={true} onClick={() => this.loadStores()} />;
|
||||||
|
|
||||||
if (isFiltered) {
|
if (isFiltered) {
|
||||||
const toggleFilters = () => userSettings.showAppliedFilters = !userSettings.showAppliedFilters;
|
const toggleFilters = () => userSettings.showAppliedFilters = !userSettings.showAppliedFilters;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<><a onClick={toggleFilters}>Filtered</a>: {itemsCount} / {allItemsCount}</>
|
<><a onClick={toggleFilters}>Filtered</a>: {itemsCount} / {allItemsCount} {RefreshIcon}</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return allItemsCount <= 1 ? `${allItemsCount} item` : `${allItemsCount} items`;
|
return allItemsCount <= 1 ? <>{allItemsCount} item {RefreshIcon}</> : <>{allItemsCount} items {RefreshIcon}</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderHeader() {
|
renderHeader() {
|
||||||
|
|||||||
@ -267,16 +267,16 @@ export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemSt
|
|||||||
}
|
}
|
||||||
|
|
||||||
subscribe(apis = this.getSubscribeApis()) {
|
subscribe(apis = this.getSubscribeApis()) {
|
||||||
const abortController = new AbortController();
|
|
||||||
let disposers: {(): void}[] = [];
|
let disposers: {(): void}[] = [];
|
||||||
|
|
||||||
const callback = (data: IKubeWatchEvent) => {
|
const callback = (data: IKubeWatchEvent) => {
|
||||||
|
if (!this.isLoaded) return;
|
||||||
|
|
||||||
this.eventsBuffer.push(data);
|
this.eventsBuffer.push(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.context.cluster.isGlobalWatchEnabled) {
|
if (this.context.cluster.isGlobalWatchEnabled) {
|
||||||
disposers = apis.map(api => api.watch({
|
disposers = apis.map(api => api.watch({
|
||||||
abortController,
|
|
||||||
namespace: "",
|
namespace: "",
|
||||||
callback: (data) => callback(data),
|
callback: (data) => callback(data),
|
||||||
}));
|
}));
|
||||||
@ -284,7 +284,6 @@ export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemSt
|
|||||||
apis.map(api => {
|
apis.map(api => {
|
||||||
this.loadedNamespaces.forEach((namespace) => {
|
this.loadedNamespaces.forEach((namespace) => {
|
||||||
disposers.push(api.watch({
|
disposers.push(api.watch({
|
||||||
abortController,
|
|
||||||
namespace,
|
namespace,
|
||||||
callback: (data) => callback(data)
|
callback: (data) => callback(data)
|
||||||
}));
|
}));
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user