class_docstr: Wraps a ServiceJobManager instance and does exception handling and cleanup.
class_docstr_tok: ["Wraps","a","ServiceJobManager","instance","and","does","exception","handling","and","cleanup","."]
code: def ensure_node_services(
      self,
      pipeline_state: pstate.PipelineState,
      node_id: str,
      backfill_token: str = "",
  ) -> ServiceStatus:
      try:
          service_status = (
              self._service_job_manager.ensure_node_services(
                  pipeline_state, node_id, backfill_token
              )
          )
      except Exception as e:  # pylint: disable=broad-except
          logging.exception(
              "Exception raised by underlying `ServiceJobManager` instance."
          )
          service_status = ServiceStatus(
              code=ServiceStatusCode.FAILED, msg=str(e)
          )
      if service_status.code == ServiceStatusCode.FAILED:
          logging.info(
              "ensure_node_services returned status `FAILED` or raised exception; "
              "calling stop_node_services (best effort) for node: %s",
              node_id,
          )
          self.stop_node_services(pipeline_state, node_id)
      return service_status
  
imports: import abc
  import dataclasses
  import enum
  from typing import Optional
  from absl import logging
  from tfx.orchestration.experimental.core import pipeline_state
label_desc: Use image node_id 2 for calling the ServiceJobManagerCleanupWrapper obj's underlying member method code with example usage: obj.ensure_node_services(pipeline_state, node_id, backfill_token) and returns: service_status