scheduler = $scheduler; } /** * Process one batch and enqueue the next when needed. * * @param int $batch Batch index (informational). * @return array{processed:int,done:bool} */ public function run_batch( $batch = 0 ) { global $wpdb; $cursor = (int) get_option( self::OPTION_CURSOR, 0 ); $writer = new PriceRevisionWriter(); $ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_type IN ('product','product_variation') AND post_status IN ('publish','private') AND ID > %d ORDER BY ID ASC LIMIT %d", $cursor, self::BATCH_SIZE ) ); $processed = 0; foreach ( (array) $ids as $id ) { $id = (int) $id; if ( ! function_exists( 'wc_get_product' ) ) { break; } $product = wc_get_product( $id ); $cursor = $id; if ( ! $product ) { continue; } $writer->observe_product( $product, 'activation', 'continuous' ); ++$processed; } update_option( self::OPTION_CURSOR, $cursor, false ); $done = empty( $ids ) || count( $ids ) < self::BATCH_SIZE; if ( $done ) { update_option( 'aksmb_price_seed_done_gmt', gmdate( 'Y-m-d H:i:s' ), false ); return array( 'processed' => $processed, 'done' => true, 'continuation_enqueued' => false, 'continuation_error' => null, ); } $continuation_enqueued = false; $continuation_error = null; if ( $this->scheduler ) { $action_id = $this->scheduler->enqueue( Constants::ACTION_SEED_PRICE_REVISIONS, array( 'batch' => (int) $batch + 1 ), Constants::SCHEDULER_GROUP, null, 'seed_' . ( (int) $batch + 1 ) ); if ( SchedulerResult::is_enqueued( $action_id ) ) { $continuation_enqueued = true; } else { $continuation_error = 'scheduler_enqueue_failed'; update_option( 'aksmb_price_seed_continuation_failed', array( 'batch' => (int) $batch + 1, 'at_gmt' => gmdate( 'Y-m-d H:i:s' ), 'error' => $continuation_error, ), false ); $this->record_continuation_event( 'price_seed', (string) ( (int) $batch + 1 ), array( 'batch' => (int) $batch + 1 ), $continuation_error ); } } else { $continuation_error = 'scheduler_unavailable'; } return array( 'processed' => $processed, 'done' => false, 'continuation_enqueued' => $continuation_enqueued, 'continuation_error' => $continuation_error, ); } /** * Best-effort operational event when WPDB is available. * * @param string $ref_type Ref type. * @param string $ref_id Ref id. * @param array $context Context. * @param string $error Error code. * @return void */ private function record_continuation_event( $ref_type, $ref_id, array $context, $error ) { global $wpdb; if ( ! isset( $wpdb ) || ! is_object( $wpdb ) || ! method_exists( $wpdb, 'insert' ) ) { return; } ( new OperationalEventsRepository() )->record( $ref_type, $ref_id, 'running', 'continuation_failed', $context, $error ); } }