9494 SnapshotFingerprint ,
9595 to_table_mapping ,
9696)
97+ from sqlmesh .core .snapshot .definition import get_next_model_interval_start
9798from sqlmesh .core .state_sync import (
9899 CachingStateSync ,
99100 StateReader ,
111112from sqlmesh .core .user import User
112113from sqlmesh .utils import UniqueKeyDict , sys_path
113114from sqlmesh .utils .dag import DAG
114- from sqlmesh .utils .date import TimeLike , now_ds , to_timestamp
115+ from sqlmesh .utils .date import TimeLike , now_ds , to_timestamp , format_tz_datetime
115116from sqlmesh .utils .errors import (
116117 CircuitBreakerError ,
117118 ConfigError ,
@@ -1951,7 +1952,7 @@ def _run(
19511952 select_models , no_auto_upstream , snapshots .values ()
19521953 )
19531954
1954- return scheduler .run (
1955+ completion_status = scheduler .run (
19551956 environment ,
19561957 start = start ,
19571958 end = end ,
@@ -1962,6 +1963,22 @@ def _run(
19621963 auto_restatement_enabled = environment .lower () == c .PROD ,
19631964 )
19641965
1966+ if completion_status .is_nothing_to_do :
1967+ next_run_ready_msg = ""
1968+
1969+ next_ready_interval_start = get_next_model_interval_start (snapshots .values ())
1970+ if next_ready_interval_start :
1971+ utc_time = format_tz_datetime (next_ready_interval_start )
1972+ local_time = format_tz_datetime (next_ready_interval_start , use_local_timezone = True )
1973+ time_msg = local_time if local_time == utc_time else f"{ local_time } ({ utc_time } )"
1974+ next_run_ready_msg = f"\n \n Next run will be ready at { time_msg } ."
1975+
1976+ self .console .log_status_update (
1977+ f"No models are ready to run. Please wait until a model `cron` interval has elapsed.{ next_run_ready_msg } "
1978+ )
1979+
1980+ return completion_status
1981+
19651982 def _apply (self , plan : Plan , circuit_breaker : t .Optional [t .Callable [[], bool ]]) -> None :
19661983 self ._scheduler .create_plan_evaluator (self ).evaluate (
19671984 plan .to_evaluatable (), circuit_breaker = circuit_breaker
0 commit comments