o
    `jh                     @  s   d Z ddlmZ ddlZddlmZ ddlmZ ddlm	Z
 ddlmZ ddlmZmZmZmZmZmZmZ ddlmZmZmZmZ dd	lmZmZ dd
lmZ erXddlmZ e e!Z"G dd dZ#G dd dZ$dS )zYPartition management mixin for KafkaAdminClient.

Also defines NewPartitions data class.
    )annotationsN)defaultdict)TYPE_CHECKING)UnknownTopicOrPartitionError)"AlterPartitionReassignmentsRequestCreatePartitionsRequestDeleteRecordsRequestDescribeTopicPartitionsRequestElectLeadersRequestElectionType!ListPartitionReassignmentsRequest)ListOffsetsRequestIsolationLevel
OffsetSpecOffsetTimestamp)TopicPartitionOffsetAndTimestamp)Timer)KafkaConnectionManagerc                   @  s   e Zd ZU dZded< ded< edd Zd.ddZdd Zd/ddZ	d/ddZ
d0ddZdd Zd1ddZedd Zd0ddZd/ddZd/dd Zd!d" Zd2d$d%Zed&d' Zed(d) Zejdfd*d+Zejdfd,d-ZdS )3PartitionAdminMixinz8Mixin providing partition and record management methods.r   _managerdictconfigc              	     s   t j}t jj g }|  D ]K\}}t|tr ||||d qt|tr;||||d  fdd|d D d q|jd urK fdd|jD }nd }||||j	|d q|S )N)namecountr   c                      g | ]} |d qS )
broker_ids .0r   _Assignmentr   U/home/djax/ivt_ai_plugin/venv/lib/python3.10/site-packages/kafka/admin/_partitions.py
<listcomp>6       zHPartitionAdminMixin._process_create_partitions_input.<locals>.<listcomp>assignments)r   r   r&   c                   r   r   r   r   r!   r   r#   r$   ;   r%   )
r   CreatePartitionsTopicCreatePartitionsAssignmentitems
isinstanceintappendr   new_assignmentstotal_count)topic_partitions_Topictopicstopicr   r-   r   r!   r#    _process_create_partitions_input)   s:   




z4PartitionAdminMixin._process_create_partitions_inputNFTc                 C  s:   |  |}t| |||d}dd }| j| j|||S )aL  Create additional partitions for an existing topic.

        Arguments:
            topic_partitions: A dict of topic name strings to total partition count (int),
                or a dict of {topic_name: {count: int, assignments: [[broker_ids]]}}
                if manual assignment is desired.
                dict of {topic_name: NewPartitions} is deprecated.

        Keyword Arguments:
            timeout_ms (numeric, optional): Milliseconds to wait for new partitions to be
                created before the broker returns.
            validate_only (bool, optional): If True, don't actually create new partitions.
                Default: False
            raise_errors (bool, optional): Whether to raise errors as exceptions. Default True.

        Returns:
            Appropriate version of CreatePartitionsResponse class.
        )r1   
timeout_msvalidate_onlyc                 s  s     | j D ]	}t|jV  qd S N)resultsErrorsfor_code
error_code)rresultr   r   r#   response_errors_   s   
z>PartitionAdminMixin.create_partitions.<locals>.response_errors)_validate_timeoutr   r3   r   run_send_request_to_controller)selfr/   r4   r5   raise_errorsrequestr=   r   r   r#   create_partitionsF   s   
z%PartitionAdminMixin.create_partitionsc           
        s   t |}t dd |D }| |I dH }tt }t  }|ddD ]'}|ddD ]}t|d |d d	}||v rI||d
  | || q+q#||kra|| }	tdddd |	D  |S )z<Finds ID of the leader node for every given topic partition.c                 s  s    | ]}|j V  qd S r6   )r2   r    tpr   r   r#   	<genexpr>g   s    zGPartitionAdminMixin._async_get_leader_for_partitions.<locals>.<genexpr>Nr1   r   
partitionsr   partition_index)r2   	partition	leader_idz*The following partitions are not known: %s, c                 s  s    | ]}t |V  qd S r6   )str)r    xr   r   r#   rG   x   s    )set_get_cluster_metadatar   getr   addr   join)
rA   rH   r1   metadataleader2partitionsvalid_partitionsr2   rJ   t2punknownr   r   r#    _async_get_leader_for_partitionsd   s,   
z4PartitionAdminMixin._async_get_leader_for_partitionsc                   s   |  |}t|}| jd d }t }i }i }|r|d u r(| |I d H }	n|t|i}	g }
|	 D ]@\}}tt}|D ]
}||j 	| q>t
 fdd| D |jd ur^t|jn|d}| jj||dI d H }|
	|  q4t }|
D ]A}|d D ]:}|d D ]3}t|d	 |d
 }|d }|tjjkr|d u r|js|| q|||< || |dkr|||< qqqz|sntdt| |}| jt|td|jpdI d H  |s|rt|dkrtt | \}}t!|d|j|j"f t#dd$dd | D  |S )Nretry_backoff_ms  c                   s&   g | ]\}}| fd d|D fqS )c                   s   g | ]	}|j  | fqS r   )rJ   rE   records_to_deleter   r#   r$      s    zHPartitionAdminMixin._async_delete_records.<locals>.<listcomp>.<listcomp>r   r    r2   partsr\   r   r#   r$      s    z=PartitionAdminMixin._async_delete_records.<locals>.<listcomp>)r1   r4   node_idr1   rH   r   rI   r:   r   z_delete_records: NotLeaderForPartitionError on %d partition(s); refreshing metadata and retrying           z1Error deleting records from topic %s partition %sz<The following errors occured when trying to delete records: rL   c                 s  s.    | ]\}}d |j |jt|jf V  qdS )z%s(partition=%d): %sN)r2   rJ   r8   r9   __name__)r    rJ   errorr   r   r#   rG      s    
z<PartitionAdminMixin._async_delete_records.<locals>.<genexpr>)%r>   r   r   rO   rY   r)   r   listr2   r,   r   r4   r+   r   sendto_dictr   r8   NotLeaderForPartitionErrorerrnoexpiredrR   discardlogdebuglen_netsleepminmaxtimeout_secsnextiterr9   rJ   BrokerResponseErrorrS   )rA   r]   r4   partition_leader_idtimerbackoff_secspendingpartition2resultpartition2errorrU   	responsesleaderrH   topic2partitionsrJ   rC   responseretry_partitionsr2   rF   err_codekeyre   r   r\   r#   _async_delete_records|   s   



$/
	z)PartitionAdminMixin._async_delete_recordsc                 C     | j | j|||S )a  Delete records whose offset is smaller than the given offset of the corresponding partition.

        Partitions whose response is :class:`~kafka.errors.NotLeaderForPartitionError`
        are retried with refreshed metadata, bounded by ``timeout_ms`` (or the
        admin client's ``request_timeout_ms`` when ``None``). When
        ``partition_leader_id`` is supplied no retry is attempted; the caller
        is asserting routing and any error is reported as-is.

        Arguments:
            records_to_delete ({TopicPartition: int}): The earliest available offsets for the
                given partitions.

        Keyword Arguments:
            timeout_ms (numeric, optional): Timeout in milliseconds. Also caps
                the total time spent retrying NotLeaderForPartitionError.
            partition_leader_id (node_id / int, optional): If specified, all deletion requests
                will be sent to this node.

        Returns:
            dict {topicPartition -> metadata}
        )r   r?   r   )rA   r]   r4   rx   r   r   r#   delete_records   s   z"PartitionAdminMixin.delete_recordsc                 C  s   dd |  |D S )Nc                 S  s&   g | ]}|d  dd |d D fqS )r   c                 S  s   g | ]}|d  qS )rI   r   r    pr   r   r#   r$      s    zLPartitionAdminMixin._get_all_topic_partitions.<locals>.<listcomp>.<listcomp>rH   r   )r    r2   r   r   r#   r$      s    zAPartitionAdminMixin._get_all_topic_partitions.<locals>.<listcomp>)describe_topics)rA   r1   r   r   r#   _get_all_topic_partitions   s   z-PartitionAdminMixin._get_all_topic_partitionsc                 C  s   t |tr	| S | |S r6   )r*   r   r)   r   )rA   r/   r   r   r#   _get_topic_partitions   s   

z)PartitionAdminMixin._get_topic_partitionsc                 C  sH   |  |}tt|| ||d}dd }tjf}| j| j||||S )a"  Trigger leader election for the specified topic partitions.

        Arguments:
            election_type: Type of election to attempt. 0 for Preferred, 1 for Unclean

        Keyword Arguments:
            topic_partitions (dict, list, optional):
                Either: dict of {topic_name: [partition ids]}.
                Or:     list of [topic_name], and election will run on all partitions for topic.
                Or:     None, and election runs against all topics / all partitions.
                Default: None
            timeout_ms (num, optional): Milliseconds to wait for the leader election process.
            raise_errors (bool, optional): Whether to raise errors as exceptions. Default True.

        Returns:
            Appropriate version of ElectLeadersResponse class.
        )election_typer/   r4   c                 s  sD    | j dkrt| jV  | jD ]}|jD ]	}t|jV  qqd S )Nrc   )API_VERSIONr8   r9   r:   replica_election_resultspartition_result)r;   r<   rJ   r   r   r#   r=     s   


z:PartitionAdminMixin.elect_leaders.<locals>.response_errors)	r>   r
   r   r   r8   ElectionNotNeededErrorr   r?   r@   )rA   r   r/   r4   rB   rC   r=   ignore_errorsr   r   r#   elect_leaders   s   
z!PartitionAdminMixin.elect_leadersc                   s   t j  j}tt}|  D ]2\}}|d ur3t|}|s#td|f tdd |D s3td|f ||j 	||j
|d q fdd| D S )NzIReplica list for %s must be non-empty; use None to cancel a reassignment.c                 s  s    | ]}t |tV  qd S r6   )r*   r+   )r    itemr   r   r#   rG     s    zSPartitionAdminMixin._process_alter_partition_reassignments_input.<locals>.<genexpr>z+Replica list for %s must be int broker_ids.)rI   replicasc                      g | ]
\}} ||d qS )r   rH   r   r^   r0   r   r#   r$   !  s    zTPartitionAdminMixin._process_alter_partition_reassignments_input.<locals>.<listcomp>)r   ReassignableTopicReassignablePartitionr   rf   r)   
ValueErrorallr2   r,   rJ   )reassignments
_Partitionr   rF   r   r   r   r#   ,_process_alter_partition_reassignments_input  s*   
z@PartitionAdminMixin._process_alter_partition_reassignments_inputc                 C  s   |  |}t|| |d}dd }| j| j||}i }|jD ] }|jD ]}t|j	|j
}	t|j}
|
tjur;|
nd||	< q%q |S )a  Alter the replica sets for the given partitions.

        Arguments:
            reassignments (dict): A dict mapping
                :class:`~kafka.TopicPartition` to a list of broker IDs
                for the new replica set, or ``None`` to cancel a
                pending reassignment for that partition.

        Keyword Arguments:
            timeout_ms (numeric, optional): The time in ms to wait for
                the request to complete.

        Raises: top-level failures that prevents processing request.
            Does not raise partition-specific errors.

        Returns:
            dict: A dict mapping each :class:`~kafka.TopicPartition`
            that the broker acknowledged to the error class for that
            partition, or ``None`` if the reassignment was accepted.
            Partitions the broker did not report on are absent from the
            dict.
        r4   r1   c                 s      t | jV  d S r6   r8   r9   r:   r;   r   r   r#   top_level_errorA     zJPartitionAdminMixin.alter_partition_reassignments.<locals>.top_level_errorN)r>   r   r   r   r?   r@   r~   rH   r   r   rI   r8   r9   r:   NoError)rA   r   r4   rC   r   r   r7   r2   rJ   rF   errr   r   r#   alter_partition_reassignments#  s"   


z1PartitionAdminMixin.alter_partition_reassignmentsc                   s   |  |}|d u rd }n1tj t|tr! fdd| D }ntt}|D ]}||j 	|j
 q' fdd| D }t||d}dd }| ||I d H }i }	|jD ]}
|
jD ]}t|jt|jt|jd|	t|
j|j< q[qV|	S )Nc                   s    g | ]\}} |t |d qS )r   partition_indexes)rf   r    r2   rH   r   r   r#   r$   V  s    zKPartitionAdminMixin._async_list_partition_reassignments.<locals>.<listcomp>c                   r   r   r   r   r   r   r#   r$   ^  s    
r   c                 s  r   r6   r   r   r   r   r#   r   h  r   zPPartitionAdminMixin._async_list_partition_reassignments.<locals>.top_level_error)r   adding_replicasremoving_replicas)r>   r    ListPartitionReassignmentsTopicsr*   r   r)   r   rf   r2   r,   rJ   r@   r1   rH   r   r   r   r   r   rI   )rA   r/   r4   topics_fieldr   rF   rC   r   r   retr2   rJ   r   r   r#   #_async_list_partition_reassignmentsN  s<   





z7PartitionAdminMixin._async_list_partition_reassignmentsc                 C  s   | j | j||S )a  List the current ongoing partition reassignments.

        Arguments:
            topic_partitions (dict, list, optional):
                Either: a dict of ``{topic_name: [partition_ids]}``,
                or a list of :class:`~kafka.TopicPartition`,
                or ``None`` to list ongoing reassignments for all partitions.
                Default: None.

        Keyword Arguments:
            timeout_ms (numeric, optional): The time in ms to wait for the
                request to complete.

        Returns:
            dict: A dict mapping :class:`~kafka.TopicPartition` to a dict
            with keys ``'replicas'``, ``'adding_replicas'``, and
            ``'removing_replicas'`` (each a list of broker IDs).
        )r   r?   r   )rA   r/   r4   r   r   r#   list_partition_reassignmentsv  s   z0PartitionAdminMixin.list_partition_reassignmentsc                   s   t j t j}|d ur||d |d d}nd }t  fdd|D ||d}| j|I d H }g }|jD ]}	|	j|	j|	j|	j	dd |	j
D |	jd}
||
 q4d }|jd ur`|jj|jjd}||d	S )
N
topic_namerI   )r   rI   c                   r   ))r   r   )r    tr   r   r#   r$     s    zHPartitionAdminMixin._async_describe_topic_partitions.<locals>.<listcomp>)r1   response_partition_limitcursorc                 S  s^   g | ]+}|j |j|j|jt|jt|j|jrt|jnd |jr%t|jnd t|j	d	qS )N)	r:   rI   rK   leader_epochreplica_nodes	isr_nodeseligible_leader_replicaslast_known_elroffline_replicas)
r:   rI   rK   r   rf   r   r   r   r   r   r   r   r   r#   r$     s    )r:   r   topic_idis_internalrH   topic_authorized_operations)r1   next_cursor)r	   TopicRequestCursorr   rg   r1   r:   r   r   r   rH   r   r,   r   r   rI   )rA   r1   r   r   _Cursorcursor_fieldrC   r   r<   r2   
topic_dictr   r   r   r#    _async_describe_topic_partitions  sB   


z4PartitionAdminMixin._async_describe_topic_partitions  c                 C  r   )a  Describe topics with fine-grained partition-level control (KIP-966).

        Unlike :meth:`describe_topics`, this uses the DescribeTopicPartitions
        API (apiKey 75, broker 3.7+) which supports pagination via a cursor
        and partition-level ELR (Eligible Leader Replicas) information.

        Arguments:
            topics ([str]): A list of topic names.

        Keyword Arguments:
            response_partition_limit (int, optional): Maximum number of
                partitions to include in the response. Default: 2000.
            cursor (dict, optional): Dict with ``'topic_name'`` and
                ``'partition_index'`` keys to start pagination from. Default:
                None.

        Returns:
            dict: ``{'topics': [...], 'next_cursor': None | {...}}``.
            ``topics`` is a list of dicts (one per topic) with keys
            ``error_code``, ``name``, ``topic_id``, ``is_internal``,
            ``partitions``, and ``topic_authorized_operations``.
            ``next_cursor`` is None if pagination is complete, otherwise a
            dict with the next page's ``topic_name`` and ``partition_index``.
        )r   r?   r   )rA   r1   r   r   r   r   r#   describe_topic_partitions  s   
z-PartitionAdminMixin.describe_topic_partitionsc                   s   t t|d}tj  j}tt}|  D ]0\}}t|t	t
fs+tdt| dt	|dk r9t t||}||j ||j|d qtd| fdd| D |dS )	Nr   zUnsupported ts type z, expected int or OffsetSpec)rI   	timestampc                   r   r   r   )r    r   r_   r   r   r#   r$     s    zGPartitionAdminMixin._list_partition_offsets_request.<locals>.<listcomp>)
replica_idisolation_levelr1   min_version)rs   r   min_version_for_isolation_levelListOffsetsTopicListOffsetsPartitionr   rf   r)   r*   r+   r   	TypeErrortypemin_version_for_timestampr2   r,   rJ   )partition_timestampsisolation_level_intr   r   r   rF   tsr   r   r#   _list_partition_offsets_request  s(   

z3PartitionAdminMixin._list_partition_offsets_requestc                 C  s   i }| j D ]:}|jD ]4}t|j|j}t|j}|tjur'|d||j	f t
|dd}t|j|j|dkr8|nd d||< q
q|S )Nz$ListOffsetsRequest failed for %s: %sr   r   r   )offsetr   r   )r1   rH   r   r   rI   r8   r9   r:   r   rd   getattrr   r   r   )r   r7   r2   rJ   rF   r   r   r   r   r#   (_list_partition_offsets_process_response  s"   


z<PartitionAdminMixin._list_partition_offsets_process_responsec              	     s  t |}t| |}| jd d }i }t| }|r| |I d H }| D ]7\}	 | 	 fdd| D |j
}
z| jj|
|	dI d H }|| | | 8 }W q* tjya   Y q*w |r|jrptdt| tdt| | jt|td|jpdI d H  |s|S )	NrZ   r[   c                   s   i | ]\}}| v r||qS r   r   )r    rF   specrH   r   r#   
<dictcomp>  s    zEPartitionAdminMixin._async_list_partition_offsets.<locals>.<dictcomp>r`   zWlist_partition_offsets timed out retrying NotLeaderForPartitionError for partitions: %szglist_partition_offsets: NotLeaderForPartitionError on %d partition(s); refreshing metadata and retryingrb   )r   
build_fromr   r>   r   rO   keysrY   r)   r   valuer   rg   updater   r8   ri   rk   sortedrm   rn   ro   rp   rq   rr   rs   rt   )rA   topic_partition_specsr   r4   ry   rz   r7   r/   rU   r   rC   r   r   r   r#   _async_list_partition_offsets  sD   
$z1PartitionAdminMixin._async_list_partition_offsetsc                 C  r   )a8  Look up offsets for the given partitions by spec.

        Partitions are routed to their respective leader brokers via cluster
        metadata; one ``ListOffsetsRequest`` is sent per leader. Partitions
        that return :class:`~kafka.errors.NotLeaderForPartitionError` are
        retried with refreshed metadata, bounded by ``timeout_ms`` (or the
        admin client's ``request_timeout_ms`` when ``None``).

        Arguments:
            topic_partition_specs: dict mapping :class:`~kafka.TopicPartition` to
                :class:`OffsetSpec` (or a raw integer timestamp /
                wire-level sentinel).

        Keyword Arguments:
            isolation_level (IsolationLevel, optional): Requires broker support
                for ListOffsets v2+. Default: IsolationLevel.READ_UNCOMMITTED.
            timeout_ms (int, optional): Maximum time to spend retrying
                NotLeaderForPartitionError. Default: ``request_timeout_ms``.

        Returns:
            dict: A dict mapping :class:`~kafka.TopicPartition` to
            :class:`~kafka.structs.OffsetAndTimestamp`

        Raises:
            KafkaError: If any partition response carries an error code.
            NotLeaderForPartitionError: If NotLeaderForPartitionError retries
                do not converge within ``timeout_ms``.
            UnknownTopicOrPartitionError: If a requested partition is not
                known to the cluster.
            UnsupportedVersionError: If the broker does not support a version
                of ListOffsetsRequest compatible with the requested specs.
        )r   r?   r   )rA   r   r   r4   r   r   r#   list_partition_offsets#  s   !
z*PartitionAdminMixin.list_partition_offsets)NFT)NNr6   )NNT)r   N)rd   
__module____qualname____doc____annotations__staticmethodr3   rD   rY   r   r   r   r   r   r   r   r   r   r   r   r   r   r   READ_UNCOMMITTEDr   r   r   r   r   r#   r   $   s4   
 



J
	
!


+
(
5

r   c                   @  s   e Zd ZdZdddZdS )NewPartitionsa!  DEPRECATED: A class for new partition creation on existing topics.

    Note that the length of new_assignments, if specified, must be the
    difference between the new total number of partitions and the existing
    number of partitions.

    Arguments:
        total_count (int): the total number of partitions that should exist
            on the topic
        new_assignments ([[int]]): an array of arrays of replica assignments
            for new partitions. If not set, broker assigns replicas per an
            internal algorithm.
    Nc                 C  s   || _ || _d S r6   )r.   r-   )rA   r.   r-   r   r   r#   __init__V  s   
zNewPartitions.__init__r6   )rd   r   r   r   r   r   r   r   r#   r   H  s    r   )%r   
__future__r   loggingcollectionsr   typingr   kafka.errorserrorsr8   r   kafka.protocol.adminr   r   r   r	   r
   r   r   kafka.protocol.consumerr   r   r   r   kafka.structsr   r   
kafka.utilr   kafka.net.managerr   	getLoggerrd   rm   r   r   r   r   r   r#   <module>   s(    $	
    (