@@ -45,37 +45,55 @@ interface AgentMetadataProps {
45
45
storybookMetadata ?: WorkspaceAgentMetadata [ ] ;
46
46
}
47
47
48
+ const maxSocketErrorRetryCount = 3 ;
49
+
48
50
export const AgentMetadata : FC < AgentMetadataProps > = ( {
49
51
agent,
50
52
storybookMetadata,
51
53
} ) => {
52
- const [ metadata , setMetadata ] = useState < WorkspaceAgentMetadata [ ] > ( ) ;
54
+ const [ activeMetadata , setActiveMetadata ] = useState ( storybookMetadata ) ;
53
55
useEffect ( ( ) => {
54
56
if ( storybookMetadata !== undefined ) {
55
57
return ;
56
58
}
57
59
58
60
let timeoutId : number | undefined = undefined ;
59
61
let latestSocket : OneWayWebSocket | undefined = undefined ;
62
+ let retries = 0 ;
60
63
61
64
const createNewConnection = ( ) => {
62
65
const socket = watchAgentMetadata ( agent . id ) ;
63
66
latestSocket = socket ;
64
67
65
68
socket . addEventListener ( "error" , ( ) => {
66
- displayError ( "Socket closed unexpectedly. Creating new connection..." ) ;
67
- setMetadata ( undefined ) ;
69
+ setActiveMetadata ( undefined ) ;
68
70
window . clearTimeout ( timeoutId ) ;
69
- timeoutId = window . setTimeout ( ( ) => {
70
- createNewConnection ( ) ;
71
- } , 3_000 ) ;
71
+
72
+ retries ++ ;
73
+ if ( retries < maxSocketErrorRetryCount ) {
74
+ displayError (
75
+ "Unexpected disconnect while watching Metadata changes. Creating new connection..." ,
76
+ ) ;
77
+ timeoutId = window . setTimeout ( ( ) => {
78
+ createNewConnection ( ) ;
79
+ } , 3_000 ) ;
80
+ return ;
81
+ }
82
+
83
+ displayError (
84
+ "Unexpected disconnect while watching Metadata changes. Cannot connect to server" ,
85
+ ) ;
86
+ // The socket should already be closed by this point, but doing
87
+ // this just to be thorough
88
+ socket . close ( ) ;
89
+ latestSocket = undefined ;
72
90
} ) ;
73
91
74
92
socket . addEventListener ( "message" , ( e ) => {
75
93
try {
76
94
const payload = JSON . parse ( e . data ) as ServerSentEvent ;
77
95
if ( payload . type === "data" ) {
78
- setMetadata ( payload . data as WorkspaceAgentMetadata [ ] ) ;
96
+ setActiveMetadata ( payload . data as WorkspaceAgentMetadata [ ] ) ;
79
97
}
80
98
} catch {
81
99
displayError (
@@ -90,17 +108,24 @@ export const AgentMetadata: FC<AgentMetadataProps> = ({
90
108
window . clearTimeout ( timeoutId ) ;
91
109
latestSocket ?. close ( ) ;
92
110
} ;
111
+
112
+ // This is an unfortunate pitfall with this component's testing setup,
113
+ // but even though we use the value of storybookMetadata as the initial
114
+ // value of the activeMetadata, we cannot put activeMetadata itself into
115
+ // the dependency array. If we did, we would destroy and rebuild each
116
+ // connection every single time a new message comes in from the socket,
117
+ // because the socket has to be wired up to the state setter
93
118
} , [ agent . id , storybookMetadata ] ) ;
94
119
95
- if ( metadata === undefined ) {
120
+ if ( activeMetadata === undefined ) {
96
121
return (
97
122
< section css = { styles . root } >
98
123
< AgentMetadataSkeleton />
99
124
</ section >
100
125
) ;
101
126
}
102
127
103
- return < AgentMetadataView metadata = { metadata } /> ;
128
+ return < AgentMetadataView metadata = { activeMetadata } /> ;
104
129
} ;
105
130
106
131
export const AgentMetadataSkeleton : FC = ( ) => {
0 commit comments