def test_update_partial_from_multiple_cloudevents(snapshot): partial = PartialSnapshot(snapshot) partial.from_cloudevent( CloudEvent({ "id": "0", "type": ids.EVTYPE_FM_JOB_RUNNING, "source": "/real/0/step/0/job/0", })) partial.from_cloudevent( CloudEvent( { "id": "0", "type": ids.EVTYPE_FM_JOB_FAILURE, "source": "/real/0/step/0/job/0", }, {ids.ERROR_MSG: "failed"}, )) partial.from_cloudevent( CloudEvent({ "id": "1", "type": ids.EVTYPE_FM_JOB_SUCCESS, "source": "/real/0/step/0/job/1", })) jobs = partial.to_dict()["reals"]["0"]["steps"]["0"]["jobs"] jobs["0"]["status"] == state.JOB_STATE_FAILURE jobs["1"]["status"] == state.JOB_STATE_FINISHED
def test_multiple_cloud_events_trigger_non_communicated_change(): """In other words, though we say all steps are finished, we don't explicitly send an event that changes the realization status. It should happen by virtue of the steps being completed.""" snapshot = (SnapshotBuilder().add_step( step_id="0", status="Unknown").build(["0"], status="Unknown")) partial = PartialSnapshot(snapshot) partial.from_cloudevent( CloudEvent({ "id": "0", "type": ids.EVTYPE_FM_STEP_SUCCESS, "source": "/real/0/step/0", })) assert partial.to_dict( )["reals"]["0"]["status"] == state.REALIZATION_STATE_FINISHED
def mock_ee_monitor(*args): reals_ids = ["0", "1"] snapshot = (SnapshotBuilder().add_stage( stage_id="0", status="Running").add_step( stage_id="0", step_id="0", status="Unknown").add_job( stage_id="0", step_id="0", job_id="0", name="job0", data={}, status="Running", ).add_metadata("iter", 0).build(reals_ids, "Unknown")) update = PartialSnapshot(snapshot) update.update_step("0", "0", "0", "Finished") update.update_step("1", "0", "0", "Finished") events = [ MockCloudEvent( {"type": ids.EVTYPE_EE_SNAPSHOT}, snapshot.to_dict(), ), MockCloudEvent( {"type": ids.EVTYPE_EE_SNAPSHOT_UPDATE}, update.to_dict(), ), MockCloudEvent({"type": ids.EVTYPE_EE_TERMINATED}, {}), ] def _track(): while True: try: yield events.pop(0) except IndexError: return return MagicMock(track=MagicMock(side_effect=_track))
def _add_partial_snapshot(self, partial: PartialSnapshot, iter_: int): partial_dict = partial.to_dict() partial_s = SnapshotDict(**partial_dict) if iter_ not in self.root.children: logger.debug("no full snapshot yet, bailing") return iter_index = self.index(iter_, 0, QModelIndex()) iter_node = self.root.children[iter_] if not partial_s.reals: logger.debug(f"no realizations in partial for iter {iter_}") return for real_id in sorted(partial_s.reals, key=int): real = partial_s.reals[real_id] real_node = iter_node.children[real_id] if real.status: real_node.data[ids.STATUS] = real.status real_index = self.index(real_node.row(), 0, iter_index) real_index_bottom_right = self.index( real_node.row(), self.columnCount(iter_index) - 1, iter_index) if not real.steps: continue for step_id, step in real.steps.items(): step_node = real_node.children[step_id] if step.status: step_node.data[ids.STATUS] = step.status step_index = self.index(step_node.row(), 0, real_index) step_index_bottom_right = self.index( step_node.row(), self.columnCount(real_index) - 1, real_index) if not step.jobs: continue for job_id in sorted(step.jobs, key=int): job = step.jobs[job_id] job_node = step_node.children[job_id] if job.status: job_node.data[ids.STATUS] = job.status if job.start_time: job_node.data[ids.START_TIME] = job.start_time if job.end_time: job_node.data[ids.END_TIME] = job.end_time if job.stdout: job_node.data[ids.STDOUT] = job.stdout if job.stderr: job_node.data[ids.STDERR] = job.stderr # Errors may be unset as the queue restarts the job job_node.data[ids.ERROR] = job.error if job.error else "" for attr in (ids.CURRENT_MEMORY_USAGE, ids.MAX_MEMORY_USAGE): if job.data and attr in job.data: job_node.data[ids.DATA][attr] = job.data.get(attr) job_index = self.index(job_node.row(), 0, step_index) job_index_bottom_right = self.index( job_node.row(), self.columnCount() - 1, step_index) self.dataChanged.emit(job_index, job_index_bottom_right) self.dataChanged.emit(step_index, step_index_bottom_right) self.dataChanged.emit(real_index, real_index_bottom_right) # TODO: there is no check that any of the data *actually* changed # https://github.com/equinor/ert/issues/1374 top_left = self.index(0, 0, iter_index) bottom_right = self.index(0, 1, iter_index) self.dataChanged.emit(top_left, bottom_right)