Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(launcher): adds default time limit submission #1976

Merged
merged 6 commits into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 9 additions & 16 deletions antarest/launcher/adapters/slurm_launcher/slurm_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -513,22 +513,15 @@ def _apply_params(self, launcher_params: LauncherParametersDTO) -> argparse.Name
):
other_options.append("xpansion_sensitivity")

time_limit = launcher_params.time_limit
if time_limit is not None:
if MIN_TIME_LIMIT > time_limit:
logger.warning(
f"Invalid slurm launcher time limit ({time_limit}),"
f" should be higher than {MIN_TIME_LIMIT}. Using min limit."
)
launcher_args.time_limit = MIN_TIME_LIMIT
elif time_limit >= MAX_TIME_LIMIT:
logger.warning(
f"Invalid slurm launcher time limit ({time_limit}),"
f" should be lower than {MAX_TIME_LIMIT}. Using max limit."
)
launcher_args.time_limit = MAX_TIME_LIMIT - 3600
else:
launcher_args.time_limit = time_limit
# The `time_limit` parameter could be `None`, in that case, the default value is used.
time_limit = launcher_params.time_limit or MIN_TIME_LIMIT
time_limit = min(max(time_limit, MIN_TIME_LIMIT), MAX_TIME_LIMIT)
if launcher_args.time_limit != time_limit:
logger.warning(
f"Invalid slurm launcher time_limit ({time_limit}),"
f" should be between {MIN_TIME_LIMIT} and {MAX_TIME_LIMIT}"
)
launcher_args.time_limit = time_limit

post_processing = launcher_params.post_processing
if post_processing is not None:
Expand Down
3 changes: 2 additions & 1 deletion antarest/launcher/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@ class LauncherParametersDTO(BaseModel):
adequacy_patch: t.Optional[t.Dict[str, t.Any]] = None
nb_cpu: t.Optional[int] = None
post_processing: bool = False
time_limit: t.Optional[int] = None # 3600 ≤ time_limit < 864000 (10 days)
time_limit: int = 240 * 3600 # Default value set to 240 hours (in seconds)
xpansion: t.Union[XpansionParametersDTO, bool, None] = None
xpansion_r_version: bool = False
archive_output: bool = True
auto_unzip: bool = True
output_suffix: t.Optional[str] = None
other_options: t.Optional[str] = None

# add extensions field here

@classmethod
Expand Down
8 changes: 5 additions & 3 deletions tests/launcher/test_slurm_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from antareslauncher.data_repo.data_repo_tinydb import DataRepoTinydb
from antareslauncher.main import MainParameters
from antareslauncher.study_dto import StudyDTO
from sqlalchemy.orm import Session # type: ignore

from antarest.core.config import Config, LauncherConfig, NbCoresConfig, SlurmConfig
from antarest.launcher.adapters.abstractlauncher import LauncherInitException
Expand All @@ -37,7 +36,7 @@ def launcher_config(tmp_path: Path) -> Config:
"key_password": "password",
"password": "password",
"default_wait_time": 10,
"default_time_limit": 20,
"default_time_limit": MAX_TIME_LIMIT,
"default_json_db_name": "antares.db",
"slurm_script_path": "/path/to/slurm/launcher.sh",
"partition": "fake_partition",
Expand Down Expand Up @@ -203,11 +202,14 @@ def test_extra_parameters(launcher_config: Config) -> None:
launcher_params = apply_params(LauncherParametersDTO(nb_cpu=999))
assert launcher_params.n_cpu == slurm_config.nb_cores.default # out of range

launcher_params = apply_params(LauncherParametersDTO.construct(time_limit=None))
assert launcher_params.time_limit == MIN_TIME_LIMIT

launcher_params = apply_params(LauncherParametersDTO(time_limit=10))
assert launcher_params.time_limit == MIN_TIME_LIMIT

launcher_params = apply_params(LauncherParametersDTO(time_limit=999999999))
assert launcher_params.time_limit == MAX_TIME_LIMIT - 3600
assert launcher_params.time_limit == MAX_TIME_LIMIT

launcher_params = apply_params(LauncherParametersDTO(time_limit=99999))
assert launcher_params.time_limit == 99999
Expand Down
28 changes: 18 additions & 10 deletions webapp/src/components/App/Studies/LauncherDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ import CheckBoxFE from "../../common/fieldEditors/CheckBoxFE";
import { convertVersions } from "../../../services/utils";
import UsePromiseCond from "../../common/utils/UsePromiseCond";
import SwitchFE from "../../common/fieldEditors/SwitchFE";
import moment from "moment";

const LAUNCH_LOAD_DEFAULT = 22;
const DEFAULT_NB_CPU = 22;
const DEFAULT_TIME_LIMIT = 240 * 3600; // 240 hours in seconds

interface Props {
open: boolean;
Expand All @@ -53,8 +55,9 @@ function LauncherDialog(props: Props) {
const { enqueueSnackbar } = useSnackbar();
const enqueueErrorSnackbar = useEnqueueErrorSnackbar();
const [options, setOptions] = useState<LaunchOptions>({
nb_cpu: LAUNCH_LOAD_DEFAULT,
nb_cpu: DEFAULT_NB_CPU,
auto_unzip: true,
time_limit: DEFAULT_TIME_LIMIT,
laurent-laporte-pro marked this conversation as resolved.
Show resolved Hide resolved
});
const [solverVersion, setSolverVersion] = useState<string>();
const [isLaunching, setIsLaunching] = useState(false);
Expand Down Expand Up @@ -170,12 +173,16 @@ function LauncherDialog(props: Props) {
// Utils
////////////////////////////////////////////////////////////////

const timeLimitParse = (value: string): number => {
try {
return parseInt(value, 10) * 3600;
} catch {
return 48 * 3600;
}
/**
* Parses an hour value from a string and converts it to seconds.
* If the input is invalid, returns a default value.
*
* @param hourString - A string representing the number of hours.
* @returns The equivalent number of seconds, or a default value for invalid inputs.
*/
const parseHoursToSeconds = (hourString: string): number => {
const seconds = moment.duration(hourString, "hours").asSeconds();
return seconds > 0 ? seconds : DEFAULT_TIME_LIMIT;
};

////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -265,9 +272,10 @@ function LauncherDialog(props: Props) {
label={t("study.timeLimit")}
type="number"
variant="filled"
value={(options.time_limit ?? 864000) / 3600} // 240 hours default
// Convert from seconds to hours the displayed value
value={(options.time_limit ?? DEFAULT_TIME_LIMIT) / 3600}
onChange={(e) =>
handleChange("time_limit", timeLimitParse(e.target.value))
handleChange("time_limit", parseHoursToSeconds(e.target.value))
}
InputLabelProps={{
shrink: true,
Expand Down
Loading