code: def _is_run_stalled(self, run_hash: str) -> bool:
      stalled = False
      heartbeat_files = list(
          sorted(
              self.heartbeat_dir.glob(f"{run_hash}-*-progress-*-*"),
              reverse=True,
          )
      )
      if heartbeat_files:
          last_heartbeat = Event(heartbeat_files[0].name)
          last_recorded_heartbeat = self.run_heartbeat_cache.get(
              run_hash
          )
          if last_recorded_heartbeat is None:
              self.run_heartbeat_cache[run_hash] = last_heartbeat
          elif last_heartbeat.idx > last_recorded_heartbeat.idx:
              self.run_heartbeat_cache[run_hash] = last_heartbeat
          else:
              time_passed = (
                  time.time()
                  - last_recorded_heartbeat.detected_epoch_time
              )
              if (
                  last_recorded_heartbeat.next_event_in
                  + RepoIndexManager.INDEXING_GRACE_PERIOD
                  < time_passed
              ):
                  stalled = True
      else:
          stalled = True
      return stalled
  
imports: import contextlib
  import time
  import datetime
  import pytz
  import logging
  import os
  from threading import Thread
  from pathlib import Path
  from typing import Iterable
  from aim.sdk.repo import Repo
  from aim.sdk.run_status_watcher import Event
  from aim.storage.locking import RefreshLock
label_desc: Use image node_id 9 for calling the RepoIndexManager obj's underlying member method code with example usage: obj._is_run_stalled(run_hash) and returns: stalled