Skip to content

Commit 50e5178

Browse files
authored
fix: aggregate cleanup chunk evidence from job data (#436)
1 parent 55e7fb7 commit 50e5178

2 files changed

Lines changed: 63 additions & 42 deletions

File tree

inc/Cleanup/DataMachineJobCleanupRunEvidenceStore.php

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@ public function read( string $run_id, bool $include_evidence = false, bool $incl
3030
return new \WP_Error( 'cleanup_run_not_found', sprintf( 'Cleanup run not found: %s', $this->cleanup_run_id( $job_id ) ), array( 'status' => 404 ) );
3131
}
3232

33-
$engine_data = $this->normalize_engine_data( $job['engine_data'] ?? array() );
34-
$child_jobs = $this->get_cleanup_run_descendant_jobs( $job_id );
35-
$aggregate = $this->aggregate_cleanup_child_jobs( $child_jobs );
36-
$children = $aggregate['children'];
37-
$state = $this->cleanup_run_state( (string) ( $job['status'] ?? '' ), $children );
33+
$engine_data = $this->normalize_engine_data( $job['engine_data'] ?? array() );
34+
$parent_result = $this->extract_system_task_result( $engine_data );
35+
$child_jobs = $this->get_cleanup_run_descendant_jobs( $job_id );
36+
$aggregate = $this->aggregate_cleanup_child_jobs( $child_jobs );
37+
$children = $aggregate['children'];
38+
$state = $this->cleanup_run_state( (string) ( $job['status'] ?? '' ), $children );
3839

3940
$children_for_output = ( $include_evidence || $include_details ) ? $children : $this->summarize_cleanup_children( $children );
4041
$output = array(
@@ -53,8 +54,8 @@ public function read( string $run_id, bool $include_evidence = false, bool $incl
5354
$output_aggregate = $aggregate;
5455
$output_aggregate['children'] = $children_for_output;
5556

56-
if ( isset( $engine_data['system_task_result'] ) && is_array( $engine_data['system_task_result'] ) ) {
57-
$engine_data['system_task_result'] = $this->with_cleanup_aggregate_report( $engine_data['system_task_result'], $output_aggregate );
57+
if ( array() !== $parent_result ) {
58+
$engine_data['system_task_result'] = $this->with_cleanup_aggregate_report( $parent_result, $output_aggregate );
5859
}
5960

6061
if ( $include_evidence ) {
@@ -130,7 +131,7 @@ private function aggregate_cleanup_child_jobs( array $child_jobs ): array {
130131
$child_job_id = (int) ( $child['job_id'] ?? 0 );
131132
$status = (string) ( $child['status'] ?? '' );
132133
$engine_data = $this->normalize_engine_data( $child['engine_data'] ?? array() );
133-
$result = is_array( $engine_data['system_task_result'] ?? null ) ? $engine_data['system_task_result'] : array();
134+
$result = $this->extract_system_task_result( $engine_data );
134135

135136
++$summary['children']['total'];
136137
if ( $child_job_id > 0 ) {
@@ -161,13 +162,16 @@ private function aggregate_cleanup_child_jobs( array $child_jobs ): array {
161162
if ( 'worktree_cleanup_chunk' !== (string) ( $engine_data['task_type'] ?? '' ) && ! isset( $result['chunk_type'] ) ) {
162163
continue;
163164
}
165+
if ( array() === $result ) {
166+
continue;
167+
}
164168

165169
if ( $child_job_id > 0 ) {
166170
$summary['children']['chunk_job_ids'][] = $child_job_id;
167171
}
168172

169173
$this->merge_cleanup_item_result( $summary['cleanup_items'], $result );
170-
if ( 'artifacts' === (string) ( $result['chunk_type'] ?? '' ) ) {
174+
if ( in_array( (string) ( $result['chunk_type'] ?? '' ), array( 'artifacts', 'artifact_discovery' ), true ) ) {
171175
$this->merge_cleanup_item_result( $summary['artifact_cleanup'], $result );
172176
}
173177
}
@@ -373,6 +377,26 @@ private function normalize_engine_data( mixed $engine_data ): array {
373377
return array();
374378
}
375379

380+
/**
381+
* Extract a task result from either nested packets or direct task engine data.
382+
*
383+
* @param array $engine_data Job engine data.
384+
* @return array<string,mixed>
385+
*/
386+
private function extract_system_task_result( array $engine_data ): array {
387+
if ( isset( $engine_data['system_task_result'] ) && is_array( $engine_data['system_task_result'] ) ) {
388+
return $engine_data['system_task_result'];
389+
}
390+
391+
foreach ( array( 'chunk_type', 'planned_count', 'applied_count', 'skipped_count', 'failed_count', 'bytes_reclaimed', 'report', 'job_backed' ) as $key ) {
392+
if ( array_key_exists( $key, $engine_data ) ) {
393+
return $engine_data;
394+
}
395+
}
396+
397+
return array();
398+
}
399+
376400
/**
377401
* Count a child job status into stable status buckets.
378402
*

tests/smoke-worktree-cleanup-cli.php

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -472,20 +472,18 @@ public function execute( array $input ): array {
472472
'source' => 'system',
473473
'status' => 'completed',
474474
'engine_data' => array(
475-
'task_type' => 'worktree_cleanup_chunk',
476-
'system_task_result' => array(
477-
'success' => true,
478-
'chunk_type' => 'artifacts',
479-
'planned_count' => 3,
480-
'applied_count' => 2,
481-
'skipped_count' => 1,
482-
'failed_count' => 0,
483-
'bytes_reclaimed' => 4096,
484-
'skipped' => array(
485-
array( 'handle' => 'repo@dirty', 'reason_code' => 'dirty_worktree' ),
486-
),
487-
'failed' => array(),
475+
'task_type' => 'worktree_cleanup_chunk',
476+
'success' => true,
477+
'chunk_type' => 'artifact_discovery',
478+
'planned_count' => 3,
479+
'applied_count' => 2,
480+
'skipped_count' => 1,
481+
'failed_count' => 0,
482+
'bytes_reclaimed' => 4096,
483+
'skipped' => array(
484+
array( 'handle' => 'repo@dirty', 'reason_code' => 'dirty_worktree' ),
488485
),
486+
'failed' => array(),
489487
),
490488
),
491489
array(
@@ -494,19 +492,17 @@ public function execute( array $input ): array {
494492
'source' => 'system',
495493
'status' => 'failed - apply_failed',
496494
'engine_data' => array(
497-
'task_type' => 'worktree_cleanup_chunk',
498-
'system_task_result' => array(
499-
'success' => false,
500-
'chunk_type' => 'artifacts',
501-
'planned_count' => 1,
502-
'applied_count' => 0,
503-
'skipped_count' => 0,
504-
'failed_count' => 1,
505-
'bytes_reclaimed' => 0,
506-
'skipped' => array(),
507-
'failed' => array(
508-
array( 'handle' => 'repo@failed', 'reason_code' => 'apply_failed' ),
509-
),
495+
'task_type' => 'worktree_cleanup_chunk',
496+
'success' => false,
497+
'chunk_type' => 'artifacts',
498+
'planned_count' => 1,
499+
'applied_count' => 0,
500+
'skipped_count' => 0,
501+
'failed_count' => 1,
502+
'bytes_reclaimed' => 0,
503+
'skipped' => array(),
504+
'failed' => array(
505+
array( 'handle' => 'repo@failed', 'reason_code' => 'apply_failed' ),
510506
),
511507
),
512508
),
@@ -542,13 +538,11 @@ public function execute( array $input ): array {
542538
'mode' => 'retention',
543539
'source' => 'workspace_cleanup_cli',
544540
),
545-
'system_task_result' => array(
546-
'success' => true,
547-
'job_backed' => true,
548-
'report' => array(
549-
'bytes_reclaimed' => 0,
550-
'freed_human' => 'pending child jobs',
551-
),
541+
'success' => true,
542+
'job_backed' => true,
543+
'report' => array(
544+
'bytes_reclaimed' => 0,
545+
'freed_human' => 'pending child jobs',
552546
),
553547
),
554548
),
@@ -689,6 +683,9 @@ public function execute( array $input ): array {
689683
datamachine_code_cleanup_assert( 4096 === (int) ( $status_json['artifact_cleanup']['bytes_reclaimed'] ?? 0 ), 'cleanup status aggregates artifact bytes from child chunks' );
690684
datamachine_code_cleanup_assert( 4 === (int) ( $status_json['cleanup_items']['planned_rows'] ?? 0 ), 'cleanup status aggregates planned rows from DB-backed cleanup item evidence' );
691685
datamachine_code_cleanup_assert( 4096 === (int) ( $status_json['cleanup_items']['bytes_reclaimed'] ?? 0 ), 'cleanup status reconstructs reclaimed bytes from cleanup item evidence' );
686+
datamachine_code_cleanup_assert( 3 === (int) ( $status_json['cleanup_items']['by_type']['artifact_discovery']['planned_rows'] ?? 0 ), 'cleanup status preserves artifact discovery chunk type aggregation' );
687+
datamachine_code_cleanup_assert( 1 === (int) ( $status_json['cleanup_items']['by_type']['artifacts']['planned_rows'] ?? 0 ), 'cleanup status preserves artifact apply chunk type aggregation' );
688+
datamachine_code_cleanup_assert( ! isset( $status_json['cleanup_items']['by_type']['unknown'] ), 'cleanup status does not aggregate completed chunks under unknown type' );
692689
datamachine_code_cleanup_assert( '4.0 KiB' === ( $status_json['system_task_result']['report']['freed_human'] ?? '' ), 'cleanup status replaces pending child job freed placeholder' );
693690
datamachine_code_cleanup_assert( ! isset( $status_json['system_task_result']['children']['job_ids'] ), 'cleanup status system task result omits full child job ids by default' );
694691

0 commit comments

Comments
 (0)