class_docstr: The execution engine will submit every model onto training service.
  
  Resource management is implemented in this class.
  
  This engine doesn't include any optimization across graphs.
  
  NOTE: Due to the design of `nni.experiment`,
  the execution engine resorts to NasExperiment to submit trials as well as waiting for results.
  This is not ideal, because this engine might be one of the very few engines which need the training service.
  Ideally, the training service should be a part of the execution engine, not the experiment.
  
  Ideally, this class should not have any states. Its save and load methods should be empty.
  
  Parameters
  ----------
  nodejs_binding
      The nodejs binding of the experiment.
  fetch_intermediates
      Whether to fetch intermediate results from the training service when list models.
      Setting it to false for large-scale experiments can improve performance.
class_docstr_tok: ["The","execution","engine","will","submit","every","model","onto","training","service",".","Resource","management","is","implemented","in","this","class",".","This","engine","does","n't","include","any","optimization","across","graphs",".","NOTE",":","Due","to","the","design","of","`","nni.experiment","`",",","the","execution","engine","resorts","to","NasExperiment","to","submit","trials","as","well","as","waiting","for","results",".","This","is","not","ideal",",","because","this","engine","might","be","one","of","the","very","few","engines","which","need","the","training","service",".","Ideally",",","the","training","service","should","be","a","part","of","the","execution","engine",",","not","the","experiment",".","Ideally",",","this","class","should","not","have","any","states",".","Its","save","and","load","methods","should","be","empty",".","Parameters","--","--","--","--","--","nodejs_binding","The","nodejs","binding","of","the","experiment",".","fetch_intermediates","Whether","to","fetch","intermediate","results","from","the","training","service","when","list","models",".","Setting","it","to","false","for","large-scale","experiments","can","improve","performance","."]
code: def __init__(
      self,
      nodejs_binding: NasExperiment,
      fetch_intermediates: bool = True,
  ) -> None:
      super().__init__()
  
      # NOTE: Currently the nodejs binding share the same instance as the experiment.
      # They will be separated in future iterations.
      self.nodejs_binding = nodejs_binding
  
      self.fetch_intermediates = fetch_intermediates
  
      # We need a model instance for callbacks.
      # They must be the exact same instance as the one submitted by the strategy.
      # The keys are parameter id (integers).
      self._models: dict[
          int, weakref.ReferenceType[ExecutableModelSpace]
      ] = dict()
  
      # Submitted models might not appear in the database instantly.
      # We need a place to track them, in case they are accessed by `list_models()`.
      self._submitted_cache: dict[int, ExecutableModelSpace] = dict()
  
      # A counter for parameters. Currently, we can only guess it based on existing trials.
      # This should also be maintained at the nodejs side.
      self._current_parameter_id: int | None = None
  
      self._workers = 0
  
      # Connect to the tuner command channel.
      self._channel = TunerCommandChannel(
          nodejs_binding.tuner_command_channel
      )
  
      self._channel.on_initialize(self._initialize_callback)
      self._channel.on_request_trial_jobs(
          self._request_trial_jobs_callback
      )
      self._channel.on_report_metric_data(
          self._report_metric_data_callback
      )
      self._channel.on_trial_end(self._trial_end_callback)
  
      self._channel.connect()
  
      self._channel_listen_stop_event = Event()
      self._channel_listen_thread = Thread(
          target=self._channel.listen,
          kwargs={
              "stop_event": self._channel_listen_stop_event  # signal to stop this thread
          },
          daemon=True,  # Set daemon to true: https://stackoverflow.com/a/58928213/6837658
      )
      self._channel_listen_thread.start()
  
      self._stopped = False
  
imports: from __future__ import annotations
  import logging
  import sys
  import time
  import weakref
  from threading import Event, Thread
  from typing import Iterable, TYPE_CHECKING, Any, cast
  import nni
  from nni.runtime.tuner_command_channel import command_type, TunerCommandChannel
  from nni.typehint import TrialMetric
  from nni.utils import MetricType
  from nni.nas.space import ExecutableModelSpace, ModelStatus, GraphModelSpace
  from .engine import ExecutionEngine
  from .event import FinalMetricEvent, IntermediateMetricEvent, TrainingEndEvent
label_desc: Use image node_id 1 to create a new TrainingServiceExecutionEngine object from inherited base classes: ExecutionEngine with example: obj = TrainingServiceExecutionEngine(nodejs_binding, fetch_intermediates)