hunk.code_window:         assert ray_error_log == "".join(ERROR_LOG_PATTERNS + ["haha"])
           assert job_driver_log == "w00t"
   if __name__ == "__main__":
       sys.exit(pytest.main(["-v", __file__]))
hunk.labels: keep keep keep add keep keep
hunk.after_edit: def test_get_last_logs_long_running_job():
       """Test calling get_last_logs() on long-running jobs.
       When the job is running longer than 4 hours, get_last_logs() should skip
       downloading the logs and return None.
       """
       anyscale_job_manager = AnyscaleJobManager(cluster_manager=None)
       anyscale_job_manager._duration = 4 * 3_600 + 1
       anyscale_job_manager._last_job_result = FakeJobResult(_id="foo")
       assert anyscale_job_manager.get_last_logs() is None
  
hunk.file_path: release/ray_release/tests/test_anyscale_job_manager.py
hunk.type: add
file: import {
    Checkbox,
    FormControlLabel,
    LinearProgress,
    makeStyles,
  } from "@material-ui/core";
  import React, { useEffect, useState } from "react";
  import { UnifiedJob } from "../../type/job";
  import {
    AdvancedProgressBar,
    AdvancedProgressBarProps,
  } from "./AdvancedProgressBar";
  import { useJobProgress, useJobProgressByLineage } from "./hook/useJobProgress";
  import { TaskProgressBar } from "./TaskProgressBar";
  
  const useStyles = makeStyles((theme) => ({
    advancedProgressBar: {
      marginTop: theme.spacing(0.5),
    },
    hideFinishedCheckbox: {
      marginRight: 0,
    },
  }));
  
  type JobProgressBarProps = {
    jobId: string | undefined;
    job: Pick<UnifiedJob, "status">;
  } & Pick<AdvancedProgressBarProps, "onClickLink">;
  
  export const JobProgressBar = ({
    jobId,
    job,
    ...advancedProgressBarProps
  }: JobProgressBarProps) => {
    const classes = useStyles();
  
    // Controls the first time we fetch the advanced progress bar data
    const [advancedProgressBarRendered, setAdvancedProgressBarRendered] =
      useState(false);
    // Controls whether we continue to fetch the advanced progress bar data
    const [advancedProgressBarExpanded, setAdvancedProgressBarExpanded] =
      useState(false);
  
    const [showFinishedTasks, setShowFinishedTasks] = useState(true);
  
    useEffect(() => {
      if (advancedProgressBarExpanded) {
        setAdvancedProgressBarRendered(true);
      }
    }, [advancedProgressBarExpanded]);
  
    const {
      progress,
      isLoading: progressLoading,
      driverExists,
      totalTasks,
      latestFetchTimestamp: progressTimestamp,
    } = useJobProgress(jobId, advancedProgressBarExpanded);
    const {
      progressGroups,
      isLoading: progressGroupsLoading,
      total,
      totalTasks: advancedTotalTasks,
      latestFetchTimestamp: totalTimestamp,
    } = useJobProgressByLineage(
      advancedProgressBarRendered ? jobId : undefined,
      !advancedProgressBarExpanded,
      showFinishedTasks,
    );
  
    if (!driverExists) {
      return <TaskProgressBar />;
    }
  
    if (
      progressLoading &&
      (progressGroupsLoading || !advancedProgressBarRendered)
    ) {
      return <LinearProgress />;
    }
  
    const { status } = job;
    // Use whichever data was received the most recently
    // Note these values may disagree in some way. It might better to consistently use one endpoint.
    const [totalProgress, finalTotalTasks] =
      total === undefined ||
      advancedTotalTasks === undefined ||
      progressTimestamp > totalTimestamp
        ? [progress, totalTasks]
        : [total, advancedTotalTasks];
  
    return (
      <div>
        <TaskProgressBar
          {...totalProgress}
          total={finalTotalTasks}
          showAsComplete={status === "SUCCEEDED" || status === "FAILED"}
          showTooltip={false}
          expanded={advancedProgressBarExpanded}
          onClick={() =>
            setAdvancedProgressBarExpanded(!advancedProgressBarExpanded)
          }
          controls={
            <FormControlLabel
              control={
                <Checkbox
                  color="primary"
                  value={!showFinishedTasks}
                  onChange={({ target: { checked } }) => {
                    setShowFinishedTasks(!checked);
                  }}
                />
              }
              label="Hide finished"
              className={classes.hideFinishedCheckbox}
            />
          }
        />
        {advancedProgressBarExpanded && (
          <AdvancedProgressBar
            className={classes.advancedProgressBar}
            progressGroups={progressGroups}
            {...advancedProgressBarProps}
          />
        )}
      </div>
    );
  };
  