Skip to content

Commit 9c969f0

Browse files
authored
fix: DH-18648: Ensure grid panel doesn't crash when Pandas query restarted (#2528)
- Taking part of deephaven-ent/iris#2572, but only need to reset the model on disconnect in G+ - The model is refetched the query is restarted - Tested against dev-gplus, created a query there with some pandas data frames
1 parent 4c2561c commit 9c969f0

File tree

1 file changed

+59
-1
lines changed

1 file changed

+59
-1
lines changed

packages/dashboard-core-plugins/src/panels/PandasPanel.tsx

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* eslint-disable react/jsx-props-no-spreading */
22
/* eslint-disable react/no-unused-state */
33
import React, { Component, type ReactElement, type RefObject } from 'react';
4+
import { IrisGridModel } from '@deephaven/iris-grid';
45
import ConnectedIrisGridPanel, {
56
type IrisGridPanel,
67
type OwnProps as IrisGridPanelOwnProps,
@@ -16,6 +17,7 @@ export interface PandasPanelProps extends IrisGridPanelOwnProps {
1617
interface PandasPanelState {
1718
shouldFocusGrid: boolean;
1819
panelState: PanelState | null;
20+
makeModel: IrisGridPanelOwnProps['makeModel'];
1921
}
2022

2123
/**
@@ -28,11 +30,17 @@ class PandasPanel extends Component<PandasPanelProps, PandasPanelState> {
2830

2931
static COMPONENT = 'PandasPanel';
3032

33+
// eslint-disable-next-line react/sort-comp
34+
private irisGridRef: RefObject<IrisGridPanel>;
35+
36+
private model: IrisGridModel | null = null;
37+
3138
constructor(props: PandasPanelProps) {
3239
super(props);
3340

3441
this.irisGridRef = React.createRef();
3542

43+
this.handleDisconnect = this.handleDisconnect.bind(this);
3644
this.handleReload = this.handleReload.bind(this);
3745
this.handleGridStateChange = this.handleGridStateChange.bind(this);
3846
this.handlePanelStateUpdate = this.handlePanelStateUpdate.bind(this);
@@ -41,10 +49,58 @@ class PandasPanel extends Component<PandasPanelProps, PandasPanelState> {
4149
this.state = {
4250
shouldFocusGrid: false,
4351
panelState, // Dehydrated panel state that can load this panel
52+
makeModel: this.wrapMakeModel(props.makeModel),
53+
};
54+
}
55+
56+
componentDidUpdate(prevProps: Readonly<PandasPanelProps>): void {
57+
const { makeModel: prevMakeModel } = prevProps;
58+
const { makeModel } = this.props;
59+
if (prevMakeModel !== makeModel) {
60+
this.setState({ makeModel: this.wrapMakeModel(makeModel) });
61+
}
62+
}
63+
64+
componentWillUnmount(): void {
65+
if (this.model != null) {
66+
this.stopListening(this.model);
67+
}
68+
}
69+
70+
private wrapMakeModel(
71+
makeModel: IrisGridPanelOwnProps['makeModel']
72+
): IrisGridPanelOwnProps['makeModel'] {
73+
return async () => {
74+
// Need to listen for disconnect in the model, so we know when to throw this makeModel away
75+
const model = await makeModel();
76+
if (this.model != null) {
77+
this.stopListening(this.model);
78+
}
79+
this.model = model;
80+
this.startListening(model);
81+
return model;
4482
};
4583
}
4684

47-
irisGridRef: RefObject<IrisGridPanel>;
85+
private startListening(model: IrisGridModel): void {
86+
model.addEventListener(
87+
IrisGridModel.EVENT.DISCONNECT,
88+
this.handleDisconnect
89+
);
90+
}
91+
92+
private stopListening(model: IrisGridModel): void {
93+
model.removeEventListener(
94+
IrisGridModel.EVENT.DISCONNECT,
95+
this.handleDisconnect
96+
);
97+
}
98+
99+
private handleDisconnect(): void {
100+
// Once a Pandas widget is closed, the underlying table is closed and cannot be reconnected to.
101+
// Reset the model to undefined so IrisGridPanel doesn't try to use it anymore.
102+
this.irisGridRef.current?.setState({ model: undefined });
103+
}
48104

49105
handleReload(): void {
50106
this.irisGridRef.current?.initModel();
@@ -70,12 +126,14 @@ class PandasPanel extends Component<PandasPanelProps, PandasPanelState> {
70126
}
71127

72128
render(): ReactElement {
129+
const { makeModel } = this.state;
73130
return (
74131
<ConnectedIrisGridPanel
75132
ref={this.irisGridRef}
76133
onStateChange={this.handleGridStateChange}
77134
onPanelStateUpdate={this.handlePanelStateUpdate}
78135
{...this.props}
136+
makeModel={makeModel}
79137
>
80138
<PandasReloadButton onClick={this.handleReload} />
81139
</ConnectedIrisGridPanel>

0 commit comments

Comments
 (0)