Open Tensorboard
+ {this.state.tensorboardReady ? (
+ ``
+ ) : (
+ Tensorboard is starting, and you may need to wait for a few minutes.
+ )}
@@ -235,6 +255,18 @@ class TensorboardViewer extends Viewer `Series${i + 1}:` + c).join(',');
}
+ private async _checkTensorboardPodStatus(): Promise {
+ // If pod address is not null and tensorboard pod doesn't seem to be read, pull status again
+ if (this.state.podAddress && !this.state.tensorboardReady) {
+ // Remove protocol prefix bofore ":" from pod address if any.
+ Apis.isTensorboardPodReady(
+ 'apis/v1beta1/_proxy/' + this.state.podAddress.replace(/(^\w+:|^)\/\//, ''),
+ ).then(ready => {
+ this.setState(({ tensorboardReady }) => ({ tensorboardReady: tensorboardReady || ready }));
+ });
+ }
+ }
+
private async _checkTensorboardApp(): Promise {
this.setState({ busy: true }, async () => {
const { podAddress, tfVersion } = await Apis.getTensorboardApp(this._buildUrl());
@@ -253,7 +285,7 @@ class TensorboardViewer extends Viewer {
+ this.setState({ busy: false, tensorboardReady: false }, () => {
this._checkTensorboardApp();
});
});
@@ -269,6 +301,7 @@ class TensorboardViewer extends Viewer {
return spy;
};
+const failedFetchSpy = (response: string) => {
+ const spy = jest.fn(() =>
+ Promise.resolve({
+ ok: false,
+ text: () => response,
+ }),
+ );
+ window.fetch = spy;
+ return spy;
+};
+
describe('Apis', () => {
it('hosts a singleton experimentServiceApi', () => {
expect(Apis.experimentServiceApi).toBe(Apis.experimentServiceApi);
@@ -182,4 +193,18 @@ describe('Apis', () => {
},
);
});
+
+ it('checks if Tensorboard pod is ready', async () => {
+ const spy = fetchSpy('');
+ const ready = await Apis.isTensorboardPodReady('apis/v1beta1/_proxy/pod_address');
+ expect(ready).toBe(true);
+ expect(spy).toHaveBeenCalledWith('apis/v1beta1/_proxy/pod_address', { method: 'HEAD' });
+ });
+
+ it('checks if Tensorboard pod is not ready', async () => {
+ const spy = failedFetchSpy('');
+ const ready = await Apis.isTensorboardPodReady('apis/v1beta1/_proxy/pod_address');
+ expect(ready).toBe(false);
+ expect(spy).toHaveBeenCalledWith('apis/v1beta1/_proxy/pod_address', { method: 'HEAD' });
+ });
});
diff --git a/frontend/src/lib/Apis.ts b/frontend/src/lib/Apis.ts
index 36777c0e48d..681fba0f5ac 100644
--- a/frontend/src/lib/Apis.ts
+++ b/frontend/src/lib/Apis.ts
@@ -204,6 +204,14 @@ export class Apis {
);
}
+ /**
+ * Check if the underlying Tensorboard pod is actually up, given the pod address
+ */
+ public static async isTensorboardPodReady(path: string): Promise {
+ const resp = await fetch(path, { method: 'HEAD' });
+ return resp.ok;
+ }
+
/**
* Delete a deployment and its service of the Tensorboard given the URL
*/