execute_batch( $batch ); $results = array_merge( $results, $batch_results ); // Small delay between batches to prevent server overload usleep( 50000 ); // 50ms } return $results; } /** * Execute a batch of queries concurrently using cURL multi-handle. * * @param array $queries Array of query strings for this batch. * @return array Results for this batch. */ private function execute_batch( $queries ) { $results = array(); // Prepare requests $requests = array(); foreach ( $queries as $query ) { $search_url = add_query_arg( 's', urlencode( $query ), home_url( '/' ) ); $requests[] = array( 'url' => $search_url, 'query' => $query, ); } // Execute in parallel $parallel_results = $this->execute_parallel_requests( $requests ); return $parallel_results; } /** * Execute multiple HTTP requests in parallel using cURL multi-handle. * * @param array $requests Array of request data (url, query). * @return array Results array. */ private function execute_parallel_requests( $requests ) { $results = array(); $mh = curl_multi_init(); $curl_handles = array(); // Add all requests to multi-handle foreach ( $requests as $index => $request ) { $ch = curl_init(); curl_setopt( $ch, CURLOPT_URL, $request['url'] ); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true ); curl_setopt( $ch, CURLOPT_TIMEOUT, 30 ); curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false ); // For local testing curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, false ); // For local testing // Add custom headers to identify test traffic (optional) curl_setopt( $ch, CURLOPT_HTTPHEADER, array( 'X-Speed-Test: MaplePress', ) ); curl_multi_add_handle( $mh, $ch ); $curl_handles[ (int) $ch ] = array( 'handle' => $ch, 'query' => $request['query'], 'start' => microtime( true ), ); } // Execute all requests $running = null; do { curl_multi_exec( $mh, $running ); curl_multi_select( $mh ); } while ( $running > 0 ); // Collect results foreach ( $curl_handles as $data ) { $info = curl_getinfo( $data['handle'] ); // Use cURL's total_time which accurately measures the individual request time // NOT the time from batch start to collection (which would be incorrect) $duration_ms = round( $info['total_time'] * 1000, 2 ); $results[] = array( 'query' => $data['query'], 'duration_ms' => $duration_ms, 'http_code' => $info['http_code'], 'timestamp' => $data['start'], 'success' => $info['http_code'] === 200, ); curl_multi_remove_handle( $mh, $data['handle'] ); curl_close( $data['handle'] ); } curl_multi_close( $mh ); return $results; } }