diff --git a/cuebot/src/main/java/com/imageworks/spcue/FrameDetail.java b/cuebot/src/main/java/com/imageworks/spcue/FrameDetail.java index 7fc4bc48a..f0c46dac2 100644 --- a/cuebot/src/main/java/com/imageworks/spcue/FrameDetail.java +++ b/cuebot/src/main/java/com/imageworks/spcue/FrameDetail.java @@ -17,11 +17,9 @@ import java.sql.Timestamp; -import com.imageworks.spcue.grpc.job.FrameState; public class FrameDetail extends FrameEntity implements FrameInterface { - public FrameState state; public int number; public int dependCount; public int retryCount; diff --git a/cuebot/src/main/java/com/imageworks/spcue/FrameEntity.java b/cuebot/src/main/java/com/imageworks/spcue/FrameEntity.java index f3b56dc9d..8a07d8f14 100644 --- a/cuebot/src/main/java/com/imageworks/spcue/FrameEntity.java +++ b/cuebot/src/main/java/com/imageworks/spcue/FrameEntity.java @@ -15,10 +15,13 @@ package com.imageworks.spcue; +import com.imageworks.spcue.grpc.job.FrameState; + public class FrameEntity extends LayerEntity implements FrameInterface { public String layerId; public int version; + public FrameState state; public FrameEntity() {} @@ -37,4 +40,8 @@ public String getLayerId() { public int getVersion() { return version; } + + public FrameState getState() { + return state; + } } diff --git a/cuebot/src/main/java/com/imageworks/spcue/FrameInterface.java b/cuebot/src/main/java/com/imageworks/spcue/FrameInterface.java index a4abfbb30..b6bbf2d9e 100644 --- a/cuebot/src/main/java/com/imageworks/spcue/FrameInterface.java +++ b/cuebot/src/main/java/com/imageworks/spcue/FrameInterface.java @@ -14,6 +14,8 @@ package com.imageworks.spcue; +import com.imageworks.spcue.grpc.job.FrameState; + public interface FrameInterface extends LayerInterface { public String getFrameId(); @@ -25,4 +27,6 @@ public interface FrameInterface extends LayerInterface { * @return the time stamp that represents the last time this frame was updated. */ public int getVersion(); + + public FrameState getState(); } diff --git a/cuebot/src/main/java/com/imageworks/spcue/dao/postgres/FrameDaoJdbc.java b/cuebot/src/main/java/com/imageworks/spcue/dao/postgres/FrameDaoJdbc.java index 2ccaef16c..84b364619 100644 --- a/cuebot/src/main/java/com/imageworks/spcue/dao/postgres/FrameDaoJdbc.java +++ b/cuebot/src/main/java/com/imageworks/spcue/dao/postgres/FrameDaoJdbc.java @@ -53,6 +53,7 @@ import com.imageworks.spcue.util.FrameSet; import com.imageworks.spcue.util.SqlUtil; +// spotless:off public class FrameDaoJdbc extends JdbcDaoSupport implements FrameDao { private static final String UPDATE_FRAME_STOPPED_NORSS = "UPDATE " + "frame " + "SET " @@ -279,6 +280,7 @@ public FrameEntity mapRow(ResultSet rs, int rowNum) throws SQLException { frame.showId = rs.getString("pk_show"); frame.facilityId = rs.getString("pk_facility"); frame.version = rs.getInt("int_version"); + frame.state = FrameState.valueOf(rs.getString("str_state")); return frame; } }; @@ -315,13 +317,29 @@ public FrameDetail mapRow(ResultSet rs, int rowNum) throws SQLException { } }; - public static final String FIND_ORPHANED_FRAMES = "SELECT " + "frame.pk_frame, " - + "frame.pk_layer, " + "frame.str_name, " + "frame.int_version, " + "job.pk_job, " - + "job.pk_show, " + "job.pk_facility " + "FROM " + "frame, " + "job " + "WHERE " - + "job.pk_job = frame.pk_job " + "AND " + "frame.str_state = 'RUNNING' " + "AND " - + "job.str_state = 'PENDING' " + "AND " - + "(SELECT COUNT(1) FROM proc WHERE proc.pk_frame = frame.pk_frame) = 0 " + "AND " - + "current_timestamp - frame.ts_updated > interval '300' second"; + public static final String FIND_ORPHANED_FRAMES = + "SELECT " + + "frame.pk_frame, " + + "frame.pk_layer, " + + "frame.str_name, " + + "frame.int_version, " + + "frame.str_state, " + + "job.pk_job, " + + "job.pk_show, " + + "job.pk_facility " + + "FROM " + + "frame, " + + "job " + + "WHERE " + + "job.pk_job = frame.pk_job " + + "AND " + + "frame.str_state = 'RUNNING' " + + "AND " + + "job.str_state = 'PENDING' " + + "AND " + + "(SELECT COUNT(1) FROM proc WHERE proc.pk_frame = frame.pk_frame) = 0 " + + "AND " + + "current_timestamp - frame.ts_updated > interval '300' second"; @Override public List getOrphanedFrames() { @@ -843,3 +861,5 @@ public void updateFrameStateDisplayOverride(String frameId, frameId, override.getState().toString()); } } + +// spotless:on diff --git a/cuebot/src/main/java/com/imageworks/spcue/service/JobManagerSupport.java b/cuebot/src/main/java/com/imageworks/spcue/service/JobManagerSupport.java index bb91ad1d8..a8fce2673 100644 --- a/cuebot/src/main/java/com/imageworks/spcue/service/JobManagerSupport.java +++ b/cuebot/src/main/java/com/imageworks/spcue/service/JobManagerSupport.java @@ -408,6 +408,15 @@ public void retryFrame(FrameInterface frame, Source source) { logger.info("failed to obtain information for " + "proc running on frame: " + frame); } + if (frame.getState() == FrameState.RUNNING) { + logger.warn("Invalid retry request. Cannot retry a running frame"); + return; + } + if (frame.getState() == FrameState.SUCCEEDED) { + logger.warn("Invalid retry request. Cannot retry a succeeded frame"); + return; + } + if (manualStopFrame(frame, FrameState.WAITING)) { if (proc != null) { redirectManager.addRedirect(proc, (JobInterface) proc, false, source); diff --git a/cuegui/cuegui/FrameMonitorTree.py b/cuegui/cuegui/FrameMonitorTree.py index ede4cd9fe..8ff397860 100644 --- a/cuegui/cuegui/FrameMonitorTree.py +++ b/cuegui/cuegui/FrameMonitorTree.py @@ -597,7 +597,7 @@ def _updateFrame(self, updatedFrame): def contextMenuEvent(self, e): """When right clicking on an item, this raises a context menu""" menu = FrameContextMenu(self, self._actionFilterSelectedLayers, - readonly=(cuegui.Constants.FINISHED_JOBS_READONLY_FRAME and + job_completed=(cuegui.Constants.FINISHED_JOBS_READONLY_FRAME and self.__jobState == opencue.api.job_pb2.FINISHED)) menu.exec_(e.globalPos()) @@ -890,7 +890,7 @@ def __saveWork(self, work, results): class FrameContextMenu(QtWidgets.QMenu): """Context menu for frames.""" - def __init__(self, widget, filterSelectedLayersCallback, readonly=False): + def __init__(self, widget, filterSelectedLayersCallback, job_completed=False): super(FrameContextMenu, self).__init__() self.app = cuegui.app() @@ -903,6 +903,12 @@ def __init__(self, widget, filterSelectedLayersCallback, readonly=False): self.__menuActions.frames().addAction(self, "view") self.__menuActions.frames().addAction(self, "copyLogPath") + can_retry = True + for frame in widget.selectedObjects(): + invalid_states = [job_pb2.FrameState.Value('RUNNING'), + job_pb2.FrameState.Value('SUCCEEDED')] + can_retry = can_retry and frame.data.state not in invalid_states + if count == 1: if widget.selectedObjects()[0].data.retry_count >= 1: self.__menuActions.frames().addAction(self, "viewLastLog") @@ -958,14 +964,15 @@ def __init__(self, widget, filterSelectedLayersCallback, readonly=False): self.__menuActions.frames().createAction(self, "Filter Selected Layers", None, filterSelectedLayersCallback, "stock-filters") - self.__menuActions.frames().addAction(self, "reorder").setEnabled(not readonly) + self.__menuActions.frames().addAction(self, "reorder").setEnabled(not job_completed) self.addSeparator() if cuegui.Constants.OUTPUT_VIEWER_DIRECT_CMD_CALL: self.__menuActions.frames().addAction(self, "previewMain") self.__menuActions.frames().addAction(self, "previewAovs") self.addSeparator() - self.__menuActions.frames().addAction(self, "retry").setEnabled(not readonly) - self.__menuActions.frames().addAction(self, "eat").setEnabled(not readonly) - self.__menuActions.frames().addAction(self, "kill").setEnabled(not readonly) - self.__menuActions.frames().addAction(self, "eatandmarkdone").setEnabled(not readonly) + self.__menuActions.frames().addAction(self, "retry").setEnabled( + can_retry and not job_completed) + self.__menuActions.frames().addAction(self, "eat").setEnabled(not job_completed) + self.__menuActions.frames().addAction(self, "kill").setEnabled(not job_completed) + self.__menuActions.frames().addAction(self, "eatandmarkdone").setEnabled(not job_completed) self.__menuActions.frames().addAction(self, "viewProcesses")