
    :j>                        d Z ddlZddlmZmZmZmZ ddlmZm	Z	 ddl
mZ ddlmZ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 ddlmZ  G d de      Z G d de      Z G d de      Z G d de      Z  ed      Z! G d d      Z"y)a  
Status Builders - System Status Construction Utilities

This module provides a robust, type-safe builder pattern implementation for constructing
SystemStatus objects with the following features:

- Type-safe interfaces with Protocol definitions for external dependencies
- Comprehensive parameter validation with custom exception types
- Dependency injection support for better testability
- Unified error handling with structured logging
- Method responsibility separation for maintainability
- Factory methods for convenient builder creation
- Build state tracking to prevent misuse

Key Components:
    StatusBuilder: Main builder class with full validation and error handling
    Custom Exceptions: Specific exception types for better error handling
    IPipelineBase: Abstract base class for pipeline implementations
    Type Protocols: Interface definitions for external dependencies

Usage Examples:
    # Basic usage with validation
    builder = StatusBuilder.quick()
    status = (builder
        .with_basic_info(runtime=10.5, state=SystemState.RUNNING)
        .with_task_metrics(completed=100, failed=2)
        .build())

    # Advanced usage with dependency injection
    custom_collector = StatusCollector(...)
    builder = StatusBuilder.create(collector=custom_collector)
    N)AnyDictListOptional)	ErrorTypeSystemState)TaskMetrics)IPipelineStats	IProvider)
get_logger   )StatusCollector)ProviderState)PerformanceMetricsPersistenceMetricsProviderStatusSystemStatus)ICollectorWithAlertsc                       e Zd ZdZy)StatusBuilderErrorz'Base exception for StatusBuilder errorsN__name__
__module____qualname____doc__     4/root/.openclaw/workspace/harvester/state/builder.pyr   r   3   s    1r   r   c                       e Zd ZdZy)BuilderAlreadyBuiltErrorzBRaised when trying to modify a builder that has already been builtNr   r   r   r   r    r    9   s    Lr   r    c                       e Zd ZdZy)InvalidParameterErrorz>Raised when invalid parameters are provided to builder methodsNr   r   r   r   r"   r"   ?   s    Hr   r"   c                       e Zd ZdZy)DataCollectionErrorz7Raised when data collection from external sources failsNr   r   r   r   r$   r$   E   s    Ar   r$   statec            	          e Zd ZdZd*dee   fdZed*dee   dd fd       Zed+d       Z	d,dZ
d	eddfd
ZdededdfdZd	ededd fdZd-dedededd fdZd.dededd fdZdedd fdZdeeef   dd fdZdeeef   ddfdZdeeef   ddfdZdeeef   dd fdZdee   dd fd Z d!ed"e!dd fd#Z"d+d$Z#d/d%ed&e$defd'Z%dee   ddfd(Z&de'fd)Z(y)0StatusBuilderzOBuilder pattern for constructing SystemStatus objects with dependency injectionN	collectorc                 >    || _         t               | _        d| _        y)zInitialize builder with dependency injection

        Args:
            collector: StatusCollector instance for pipeline data collection
        FN)r(   r   status_built)selfr(   s     r   __init__zStatusBuilder.__init__Q   s     #"nr   returnc                      | |      S )zFactory method to create a new StatusBuilder instance

        Args:
            collector: Optional StatusCollector instance

        Returns:
            New StatusBuilder instance
        r   )clsr(   s     r   createzStatusBuilder.create[   s     9~r   c                      |        S )zCreate a StatusBuilder with default dependencies for quick usage

        Returns:
            StatusBuilder with default dependencies
        r   )r0   s    r   quickzStatusBuilder.quickg   s     ur   c                 2    | j                   rt        d      y)z$Ensure builder hasn't been built yetz9Cannot modify StatusBuilder after build() has been calledN)r+   r    )r,   s    r   _ensure_not_builtzStatusBuilder._ensure_not_builtp   s    ;;*+fgg r   runtimec                 V    t        |t        t        f      r|dk  rt        d|       y)zValidate runtime parameterr   z,Runtime must be a non-negative number, got: N)
isinstanceintfloatr"   )r,   r6   s     r   _validate_runtimezStatusBuilder._validate_runtimeu   s1    'C<0GaK'*VW^V_(`aa 5@r   	operationerrorc                 ~   d| d|j                   j                   d| }t        j                  |       t	        | j
                  t              rA	 | j
                  j                  | j                  t        j                  j                  |       yy# t        $ r"}t        j                  d|        Y d}~yd}~ww xY w)zHandle data collection errors consistently

        Args:
            operation: Description of the operation that failed
            error: The original exception
        z
Failed to : zFailed to add error alert: N)	__class__r   loggerr=   r8   r(   r   _add_error_alertr*   r   DATA_COLLECTION_ERRORvalue	Exceptionwarning)r,   r<   r=   	error_msgalert_errors        r   _handle_collection_errorz&StatusBuilder._handle_collection_errorz   s     !2eoo.F.F-Gr%Q	Y dnn&:;L//Y=\=\=b=bdij <  L!<[MJKKLs   ?B 	B<B77B<r%   c                     | j                          | j                  |       || j                  _        || j                  _        t        j
                         | j                  _        | S )ak  Set basic system information

        Args:
            runtime: System runtime in seconds (must be non-negative)
            state: Current system state

        Returns:
            Self for method chaining

        Raises:
            BuilderAlreadyBuiltError: If builder has already been built
            InvalidParameterError: If runtime is invalid
        )r5   r;   r*   r6   r%   time	timestamp)r,   r6   r%   s      r   with_basic_infozStatusBuilder.with_basic_info   sM     	 w'%! $		r   	completedfailedpendingc                     | j                          d|fd|fd|ffD ]*  \  }}t        |t              r|dk  st        | d|        t	        |||      | j
                  _        | S )a  Set task metrics

        Args:
            completed: Completed tasks (must be non-negative)
            failed: Failed tasks (must be non-negative)
            pending: Pending tasks (must be non-negative)

        Returns:
            Self for method chaining

        Raises:
            RuntimeError: If builder has already been built
            ValueError: If any metric is negative
        rN   rO   rP   r   z& must be a non-negative integer, got: )rN   rO   rP   )r5   r8   r9   r"   r	   r*   tasks)r,   rN   rO   rP   namerD   s         r   with_task_metricszStatusBuilder.with_task_metrics   s     	  ))4x6H9V]J^_ 	dKD%eS)UQY+tf4Z[`Za,bcc	d ()FT[\r   
throughputsuccess_ratec                 *   | j                          t        |t        t        f      r|dk  rt	        d|       t        |t        t        f      rd|cxk  rdk  sn t	        d|       t        ||||dkD  rd|z
  nd      | j                  _        | S )ar  Set performance metrics

        Args:
            throughput: Tasks per second (must be non-negative)
            success_rate: Success rate (must be between 0.0 and 1.0)

        Returns:
            Self for method chaining

        Raises:
            RuntimeError: If builder has already been built
            ValueError: If metrics are out of valid range
        r   z&Throughput must be non-negative, got:         g      ?z/Success rate must be between 0.0 and 1.0, got: )rU   tasks_per_secondrV   
error_rate)r5   r8   r9   r:   r"   r   r*   performance)r,   rU   rV   s      r   with_performance_metricsz&StatusBuilder.with_performance_metrics   s     	  *sEl3zA~'*PQ[P\(]^^,e5c\>XUX>X'*YZfYg(hii"4!'%-9A-=s\)3	#
 r   pipelinec                 j   | j                          |r%	 	 |j                         }|| j                  _        | S | S # t        $ rF |j                         }t        j                  dt        |              || j                  _        Y | S w xY w# t        $ r}| j                  d|       Y d}~| S d}~ww xY w)a  Set pipeline statistics using collector

        Args:
            pipeline: Pipeline object implementing IPipelineBase interface

        Returns:
            Self for method chaining

        Raises:
            RuntimeError: If builder has already been built
        zGot dynamic pipeline stats: zcollect pipeline statisticsN)r5   get_all_statsr*   r]   AttributeErrorget_dynamic_statsrA   debugtyperE   rI   )r,   r]   pipeline_statses       r   with_pipeline_statsz!StatusBuilder.with_pipeline_stats   s     	 P:%-%;%;%=N+9DKK( t & :%-%?%?%ANLL#?^@T?U!VW+9DKK(
 :  P--.KQOOPs.   !: AB	B B		B 	B2B--B2result_statsc                 n    | j                          |r"| j                  |       | j                  |       | S )a1  Set result statistics using direct field mapping

        Args:
            result_stats: Dictionary mapping provider names to their persistence metrics

        Returns:
            Self for method chaining

        Raises:
            BuilderAlreadyBuiltError: If builder has already been built
        )r5   _update_system_level_metrics_update_provider_level_metrics)r,   rg   s     r   with_result_statszStatusBuilder.with_result_stats   s4     	 --l;//=r   c                 Z   	 | j                  |       | j                  j                          t        j	                  d| j                  j
                  j                   d| j                  j
                  j                          y# t        $ r}| j                  d|       Y d}~yd}~ww xY w)zzUpdate system-level aggregated metrics

        Args:
            result_stats: Dictionary of provider statistics
        zUpdated system metrics: keys=, links=zupdate system-level metricsN)
rj   r*   calculate_overall_metricsrA   rb   resourcetotallinksrE   rI   )r,   rg   re   s      r   ri   z*StatusBuilder._update_system_level_metrics  s    	L//=KK113LL/0D0D0J0J/K8TXT_T_ThThTnTnSop  	L))*GKK	Ls   BB 	B*B%%B*c           	      ,   |j                         D ]  \  }}|rt        |t              st        j	                  d| d|        4	 || j
                  j                  v rq| j
                  j                  |   }|j                  |_        t        j                  d| d|j                  j                   d|j                  j                          nt        j	                  d| d        y	# t        $ r}| j                  d| |       Y d	}~d	}~ww xY w)
zvUpdate individual provider metrics

        Args:
            result_stats: Dictionary of provider statistics
        zSkip update provider z due to invalid metrics: Updated provider z metrics: valid=rm   z	Provider z7 not found in status.providers, skipping metrics updatezupdate metrics for provider N)itemsr8   r   rA   rF   r*   	providersro   rb   validrq   rE   rI   )r,   rg   rS   statsprovider_statusre   s         r   rj   z,StatusBuilder._update_provider_level_metrics  s&    (--/ 	XKD%
52D E!6tf<UV[U\]^
X4;;000&*kk&;&;D&AO/4~~O,LL+D61A/BZBZB`B`Aaaijy  kC  kC  kI  kI  jJ  K NNYtf4k#lm	X  X--0LTF.SUVWWXs   B"C++	D4DDru   c                     |r?|j                         D ],  }| j                  |      }|| j                  j                  |<   . | S )zSet providers information

        Args:
            providers: Dictionary mapping provider names to Provider instances

        Returns:
            Self for method chaining
        )keys_create_provider_statusr*   ru   )r,   ru   rS   r*   s       r   with_providers_infoz!StatusBuilder.with_providers_info4  sH     !( 555d;.4%%d+5 r   provider_statusesc                     | j                          t        j                  d|rt        |      nd d       |r| j	                  |       | S )a
  Set provider stage configurations

        Args:
            stages: List of provider stage configuration objects

        Returns:
            Self for method chaining

        Raises:
            BuilderAlreadyBuiltError: If builder has already been built
        z/StatusBuilder.with_provider_stages called with r   z stages)r5   rA   rb   len_update_provider_status)r,   r}   s     r   with_provider_statusz"StatusBuilder.with_provider_statusE  sO     	 =XicBS>Top=qqxy	
 (():;r   fieldrD   c                     | j                          t        | j                  |      st        d| d      t	        | j                  ||       t
        j                  d| d|        | S )af  Set a custom field on the status object

        Args:
            field: Name of the field to set
            value: Value to set

        Returns:
            Self for method chaining

        Raises:
            BuilderAlreadyBuiltError: If builder has already been built
            InvalidParameterError: If field doesn't exist on status object
        zStatus object has no field ''zSet custom field  = )r5   hasattrr*   r"   setattrrA   rb   )r,   r   rD   s      r   with_custom_fieldzStatusBuilder.with_custom_fieldZ  sb     	 t{{E*'*FugQ(OPPUE*(s5':;r   c                 |   | j                          |j                         D ]g  \  }}	 t        | j                  |      r3t	        | j                  ||       t
        j                  d| d|        nt
        j                  d|        i | S # t        $ r%}t
        j                  d| d|        Y d}~d}~ww xY w)a   Set additional data fields

        Args:
            **kwargs: Additional data to set as custom fields

        Returns:
            Self for method chaining

        Raises:
            BuilderAlreadyBuiltError: If builder has already been built
        zSet additional field r   zSkipping unknown field zFailed to set additional field r?   N)	r5   rt   r   r*   r   rA   rb   rE   rF   )r,   kwargsr   rD   re   s        r   with_additional_dataz"StatusBuilder.with_additional_dataq  s     	 "LLN 	OLE5O4;;.DKK6LL#8s5'!JKLL#:5'!BC	O   O!@r!MNNOs   A!B	B;B66B;rS   enabledc                 h    t        |||rt        j                        S t        j                        S )zCreate a ProviderStatus object with default values

        Args:
            name: Name of the provider
            enabled: Whether the provider is enabled

        Returns:
            ProviderStatus: Configured provider status object
        )rS   r   r%   )r   r   ACTIVEDISABLED)r,   rS   r   s      r   r{   z%StatusBuilder._create_provider_status  s8     *1-&&
 	
 8E7M7M
 	
r   c                    	 |D ](  }|j                   | j                  j                  v r| j                  j                  |j                      }|j                  |_        |j                  |_        |j
                  |_        |j                  |_        t        j                  d|j                    d|j                   d|j                   d|j
                   d|j                   
       t        j                  d|j                           || j                  j                  |j                   <   + y# t        $ r}| j                  d|       Y d}~yd}~ww xY w)	z$Update provider stage configurationsrs   z stages: S=z, G=z, V=z, I=z!Creating new provider status for zupdate provider stagesN)rS   r*   ru   
searchable
gatherable	checkableinspectablerA   rb   rE   rI   )r,   r}   rx   psre   s        r   r   z%StatusBuilder._update_provider_status  sM   	G#4 R"''4;;+@+@@../C/CDB$3$>$>BM$3$>$>BM#2#<#<BL%4%@%@BNLL+O,@,@+AR]]O[_`b`m`m_nnrsuss  sA  AE  FH  FT  FT  EU  V
 LL#D_EYEYDZ![\BQDKK))/*>*>?R  	G))*BAFF	Gs   D.D1 1	E:EEc                     | j                   rt        d      	 | j                  j                          d| _         | j                  S # t        $ r"}t
        j                  d|        Y d}~9d}~ww xY w)zBuild final SystemStatus object

        Returns:
            Constructed SystemStatus object

        Raises:
            BuilderAlreadyBuiltError: If build() has already been called
        z:build() can only be called once per StatusBuilder instancez%Failed to calculate derived metrics: NT)r+   r    r*   rn   rE   rA   rF   )r,   re   s     r   buildzStatusBuilder.build  sk     ;;*+ghh	HKK113 {{	  	HNNB1#FGG	Hs   A 	A1A,,A1)N)r.   r'   )r.   N)r   r   r   )rX   rX   )T))r   r   r   r   r   r   r-   classmethodr1   r3   r5   r:   r;   strrE   rI   r   rM   r9   rT   r\   r
   rf   r   r   rk   ri   rj   r   r|   r   r   r   r   r   r   boolr{   r   r   r   r   r   r   r'   r'   N   s   Y(?";  	x8 	O 	 	  h
b b4 b
L# Li LD L&u [ _ ,3 C c Zi 25 e ^m <N  >d38J3J.K P_ (LcCU>U9V L[_ L X4EW@W;X X]a X.T#y.-A o "d>6J  *s 3 ? .4
C 
$ 
. 
 Gn9M GRV G*| r   r'   )#r   rK   typingr   r   r   r   
core.enumsr   r   core.metricsr	   
core.typesr
   r   tools.loggerr   r(   r   enumsr   modelsr   r   r   r   typesr   rE   r   r    r"   r$   rA   r'   r   r   r   <module>r      s|   B  , , - $ 0 # &   X X '	 		1 		. 		, 	 
G	u ur   