Skip to content

Commit 90d2d17

Browse files
[cuegui] Add error handling for gRPC connection failures in FrameMonitor (#2079)
**Link the Issue(s) this Pull Request is related to.** - #2078 **Summarize your change.** When gRPC connections are interrupted or reset by the network/load balancer, CueGUI would freeze and display "rpcObjects is None" errors, requiring users to restart the application. This change adds graceful error handling to _filterLayersUpdate() and _frameRangeSelectionFilterUpdate() to catch grpc.RpcError exceptions and allow the UI to continue functioning. Changes: - Import grpc module in FrameMonitor.py - Wrap getLayers() calls in try/except blocks - Log appropriate warnings for connection interruptions - Return empty lists on failure to allow graceful degradation - UI remains responsive and auto-recovers when connection is restored This follows the same error handling pattern already used in FrameMonitorTree._getUpdate() and _getUpdateChanged().
1 parent 1705100 commit 90d2d17

File tree

1 file changed

+51
-25
lines changed

1 file changed

+51
-25
lines changed

cuegui/cuegui/FrameMonitor.py

Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from qtpy import QtCore
2828
from qtpy import QtGui
2929
from qtpy import QtWidgets
30+
import grpc
3031

3132
import FileSequence
3233
from opencue_proto import job_pb2
@@ -131,31 +132,44 @@ def _frameRangeSelectionFilterUpdate(self):
131132
if not self.frameMonitorTree.getJob():
132133
self.frameRangeSelection.setFrameRange(["1", str(self.frameSearchLimit)])
133134
else:
134-
layers = self.frameMonitorTree.getJob().getLayers()
135-
136-
_min = None
137-
_max = None
138-
139-
for layer in layers:
140-
seq = FileSequence.FrameSet(layer.range())
141-
seq.normalize()
142-
frameList = seq.getAll()
143-
if _min is not None:
144-
_min = min(_min, int(frameList[0]))
145-
else:
146-
_min = int(frameList[0])
147-
148-
if _max is not None:
149-
_max = max(_max, int(frameList[-1]))
135+
try:
136+
layers = self.frameMonitorTree.getJob().getLayers()
137+
138+
_min = None
139+
_max = None
140+
141+
for layer in layers:
142+
seq = FileSequence.FrameSet(layer.range())
143+
seq.normalize()
144+
frameList = seq.getAll()
145+
if _min is not None:
146+
_min = min(_min, int(frameList[0]))
147+
else:
148+
_min = int(frameList[0])
149+
150+
if _max is not None:
151+
_max = max(_max, int(frameList[-1]))
152+
else:
153+
_max = int(frameList[-1])
154+
155+
if _min == _max:
156+
_max += 1
157+
158+
self.frameRangeSelection.default_select_size = self.frameSearchLimit // len(layers)
159+
160+
self.frameRangeSelection.setFrameRange([str(_min), str(_max)])
161+
except grpc.RpcError as e:
162+
# Handle gRPC connection errors gracefully
163+
# pylint: disable=no-member
164+
if hasattr(e, 'code') and e.code() in [grpc.StatusCode.CANCELLED,
165+
grpc.StatusCode.UNAVAILABLE]:
166+
log.warning(
167+
"gRPC connection interrupted while updating frame range filter, will retry")
150168
else:
151-
_max = int(frameList[-1])
152-
153-
if _min == _max:
154-
_max += 1
155-
156-
self.frameRangeSelection.default_select_size = self.frameSearchLimit // len(layers)
157-
158-
self.frameRangeSelection.setFrameRange([str(_min), str(_max)])
169+
log.error("gRPC error in _frameRangeSelectionFilterUpdate: %s", e)
170+
# pylint: enable=no-member
171+
# Set a default range if we can't get layers
172+
self.frameRangeSelection.setFrameRange(["1", str(self.frameSearchLimit)])
159173

160174
def _frameRangeSelectionFilterHandle(self, start, end):
161175
self.frameMonitorTree.frameSearch.options['range'] = "%s-%s" % (start, end)
@@ -354,7 +368,19 @@ def _filterLayersUpdate(self):
354368
menu.triggered[QtWidgets.QAction].connect(self._filterLayersHandle) # pylint: disable=unsubscriptable-object
355369

356370
if self.frameMonitorTree.getJob():
357-
layers = [x.data.name for x in self.frameMonitorTree.getJob().getLayers()]
371+
try:
372+
layers = [x.data.name for x in self.frameMonitorTree.getJob().getLayers()]
373+
except grpc.RpcError as e:
374+
# Handle gRPC connection errors gracefully
375+
# pylint: disable=no-member
376+
if hasattr(e, 'code') and e.code() in [grpc.StatusCode.CANCELLED,
377+
grpc.StatusCode.UNAVAILABLE]:
378+
log.warning(
379+
"gRPC connection interrupted while updating layer filter, will retry")
380+
else:
381+
log.error("gRPC error in _filterLayersUpdate: %s", e)
382+
# pylint: enable=no-member
383+
layers = []
358384
else:
359385
layers = []
360386

0 commit comments

Comments
 (0)