class_docstr: InstanceLauncher is responsible for provisioning new instances.
code: def notify(self, events: List[InstanceUpdateEvent]) -> None:
      # TODO: we should do reconciliation based on events.
      has_new_request = any(
          [
              event.new_instance_status == Instance.UNKNOWN
              for event in events
          ]
      )
      if has_new_request:
          self._executor.submit(self._may_launch_new_instances)
  
file_path: ray/python/ray/autoscaler/v2/instance_manager/subscribers/instance_launcher.py
imports: import logging
  import math
  from collections import defaultdict
  from concurrent.futures import ThreadPoolExecutor
  from typing import List
  from ray.autoscaler._private.constants import AUTOSCALER_MAX_CONCURRENT_LAUNCHES, AUTOSCALER_MAX_LAUNCH_BATCH
  from ray.autoscaler.v2.instance_manager.instance_storage import InstanceStorage, InstanceUpdatedSubscriber
  from ray.autoscaler.v2.instance_manager.node_provider import NodeProvider
  from ray.core.generated.instance_manager_pb2 import Instance, InstanceUpdateEvent
label_desc: Use image node_id 2 for calling the InstanceLauncher obj's underlying member method code with example usage: obj.notify(events) without return types