async def create_job_async(
        self,
        project_id: str,
        program_id: str,
        job_id: str | None,
        processor_id: str,
        run_context: any_pb2.Any = any_pb2.Any(),
        priority: int | None = None,
        description: str | None = None,
        labels: dict[str, str] | None = None,
        *,
        run_name: str = "",
        snapshot_id: str = "",
        device_config_name: str = "",
    ) -> tuple[str, quantum.QuantumJob]:
        """Creates and runs a job on Quantum Engine.

        Either both `run_name` and `device_config_name` must be set, or neither
        of them must be set. If none of them are set, a default internal device
        configuration will be used.

        Args:
            project_id: A project_id of the parent Google Cloud Project.
            program_id: Unique ID of the program within the parent project.
            job_id: Unique ID of the job within the parent program.
            run_context: Properly serialized run context.
            priority: Optional priority to run at, 0-1000.
            description: Optional description to set on the job.
            labels: Optional set of labels to set on the job.
            processor_id: Processor id for running the program.
            run_name: A unique identifier representing an automation run for the
                specified processor. An Automation Run contains a collection of
                device configurations for a processor. If specified, `processor_id`
                is required to be set.
            snapshot_id: A unique identifier for an immutable snapshot reference.
                A snapshot contains a collection of device configurations for the
                processor.
            device_config_name: An identifier used to select the processor configuration
                utilized to run the job. A configuration identifies the set of
                available qubits, couplers, and supported gates in the processor.
                If specified, `processor_id` is required to be set.
        Returns:
            Tuple of created job id and job.

        Raises:
            ValueError: If the priority is not between 0 and 1000.
            ValueError: If  only one of `run_name` and `device_config_name` are specified.
            ValueError: If either `run_name` and `device_config_name` are set but
                `processor_id` is empty.
            ValueError: If both `run_name` and `snapshot_id` are specified.
        """
        # Check program to run and program parameters.
        if priority and not 0 <= priority < 1000:
            raise ValueError('priority must be between 0 and 1000')
        if not processor_id:
            raise ValueError('Must specify a processor id when creating a job.')
        if run_name and snapshot_id:
            raise ValueError('Cannot specify both `run_name` and `snapshot_id`')
        if (bool(run_name) or bool(snapshot_id)) ^ bool(device_config_name):
            raise ValueError(
                'Cannot specify only one of top level identifier (e.g `run_name`, `snapshot_id`)'
                ' and `device_config_name`'
            )

        # Create job.
        if snapshot_id:
            selector = quantum.DeviceConfigSelector(
                snapshot_id=snapshot_id or None, config_alias=device_config_name
            )
        else:
            selector = quantum.DeviceConfigSelector(
                run_name=run_name or None, config_alias=device_config_name
            )
        job_name = _job_name_from_ids(project_id, program_id, job_id) if job_id else ''
        job = quantum.QuantumJob(
            name=job_name,
            scheduling_config=quantum.SchedulingConfig(
                processor_selector=quantum.SchedulingConfig.ProcessorSelector(
                    processor=_processor_name_from_ids(project_id, processor_id),
                    device_config_selector=selector,
                )
            ),
            run_context=run_context,
        )
        if priority:
            job.scheduling_config.priority = priority
        if description:
            job.description = description
        if labels:
            job.labels.update(labels)
        request = quantum.CreateQuantumJobRequest(
            parent=_program_name_from_ids(project_id, program_id), quantum_job=job
        )
        job = await self._send_request_async(self.grpc_client.create_quantum_job, request)
        return _ids_from_job_name(job.name)[2], job
Creates and runs a job on Quantum Engine.

        Either both `run_name` and `device_config_name` must be set, or neither
        of them must be set. If none of them are set, a default internal device
        configuration will be used.

        Args:
            project_id: A project_id of the parent Google Cloud Project.
            program_id: Unique ID of the program within the parent project.
            job_id: Unique ID of the job within the parent program.
            run_context: Properly serialized run context.
            priority: Optional priority to run at, 0-1000.
            description: Optional description to set on the job.
            labels: Optional set of labels to set on the job.
            processor_id: Processor id for running the program.
            run_name: A unique identifier representing an automation run for the
                specified processor. An Automation Run contains a collection of
                device configurations for a processor. If specified, `processor_id`
                is required to be set.
            snapshot_id: A unique identifier for an immutable snapshot reference.
                A snapshot contains a collection of device configurations for the
                processor.
            device_config_name: An identifier used to select the processor configuration
                utilized to run the job. A configuration identifies the set of
                available qubits, couplers, and supported gates in the processor.
                If specified, `processor_id` is required to be set.
        Returns:
            Tuple of created job id and job.

        Raises:
            ValueError: If the priority is not between 0 and 1000.
            ValueError: If  only one of `run_name` and `device_config_name` are specified.
            ValueError: If either `run_name` and `device_config_name` are set but
                `processor_id` is empty.
            ValueError: If both `run_name` and `snapshot_id` are specified.
        
cirq-google/cirq_google/engine/engine_client.py