Fix false stall detection for multi-article chained generation

The frontend status poller measured elapsed time from `started` (set once
at the beginning of the run) and declared a stall at 300s.  Three articles
take ~6 minutes total, so the poller always false-alarmed on article 3.

Now every stage broadcast writes `last_updated` into the transient, and
the stall check compares idle time since the last update — not since the
run started.  This lets N-article runs complete without false timeout as
long as each individual article finishes within 5 minutes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
peptiderepo
2026-04-19 03:40:05 +07:00
parent ef40ce91d4
commit cc6979b085
3 changed files with 19 additions and 16 deletions

View File

@@ -108,6 +108,7 @@ class PRAutoBlogger_Executor {
'status' => 'running', 'status' => 'running',
'stage' => __( 'Starting generation...', 'prautoblogger' ), 'stage' => __( 'Starting generation...', 'prautoblogger' ),
'started' => time(), 'started' => time(),
'last_updated' => time(),
], self::STATUS_TTL ); ], self::STATUS_TTL );
// Schedule immediate one-shot cron event. WordPress will fire this // Schedule immediate one-shot cron event. WordPress will fire this
@@ -190,11 +191,7 @@ class PRAutoBlogger_Executor {
} }
} }
/** /** Cron handler: process next queued article. Chained by Pipeline_Runner. */
* Cron handler: process the next queued article in its own PHP process.
*
* Chained by Pipeline_Runner — each article gets its own execution time.
*/
public function on_process_article_queue(): void { public function on_process_article_queue(): void {
// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
@ignore_user_abort( true ); @ignore_user_abort( true );
@@ -249,8 +246,10 @@ class PRAutoBlogger_Executor {
} }
} }
// After 5 min with no progress, declare failure. // Stall = 5 min since last stage update (not since start).
if ( $elapsed > 300 ) { $last_activity = $status['last_updated'] ?? $status['started'] ?? 0;
$idle_seconds = time() - $last_activity;
if ( $idle_seconds > 300 ) {
$this->abort_orphaned_run( __( 'Generation stalled. Check Activity Log.', 'prautoblogger' ) ); $this->abort_orphaned_run( __( 'Generation stalled. Check Activity Log.', 'prautoblogger' ) );
return; return;
} }
@@ -276,6 +275,7 @@ class PRAutoBlogger_Executor {
$current = get_transient( self::STATUS_TRANSIENT ); $current = get_transient( self::STATUS_TRANSIENT );
if ( is_array( $current ) ) { if ( is_array( $current ) ) {
$current['stage'] = $stage; $current['stage'] = $stage;
$current['last_updated'] = time();
set_transient( self::STATUS_TRANSIENT, $current, self::STATUS_TTL ); set_transient( self::STATUS_TRANSIENT, $current, self::STATUS_TTL );
} }
} }

View File

@@ -138,6 +138,7 @@ class PRAutoBlogger_Article_Worker {
$current = get_transient( $transient_key ); $current = get_transient( $transient_key );
if ( is_array( $current ) && 'running' === ( $current['status'] ?? '' ) ) { if ( is_array( $current ) && 'running' === ( $current['status'] ?? '' ) ) {
$current['stage'] = $stage; $current['stage'] = $stage;
$current['last_updated'] = time();
set_transient( $transient_key, $current, 600 ); set_transient( $transient_key, $current, 600 );
} }
} }

View File

@@ -216,6 +216,7 @@ class PRAutoBlogger_Pipeline_Runner {
'status' => 'running', 'status' => 'running',
'stage' => sprintf( __( 'Generating article %1$d of %2$d…', 'prautoblogger' ), $done + 1, $total ), 'stage' => sprintf( __( 'Generating article %1$d of %2$d…', 'prautoblogger' ), $done + 1, $total ),
'started' => is_array( $current ) ? ( $current['started'] ?? time() ) : time(), 'started' => is_array( $current ) ? ( $current['started'] ?? time() ) : time(),
'last_updated' => time(),
], 600 ); ], 600 );
} }
@@ -257,6 +258,7 @@ class PRAutoBlogger_Pipeline_Runner {
$current = get_transient( $key ); $current = get_transient( $key );
if ( is_array( $current ) && 'running' === ( $current['status'] ?? '' ) ) { if ( is_array( $current ) && 'running' === ( $current['status'] ?? '' ) ) {
$current['stage'] = $stage; $current['stage'] = $stage;
$current['last_updated'] = time();
set_transient( $key, $current, 600 ); set_transient( $key, $current, 600 );
} }
} }