feat: parallel image generation via curl_multi

Both Image A and Image B now fire concurrently through a single
generate_image_batch() call instead of sequentially. Total wall-clock
time equals the slowest image (~20s), not the sum (~40s), which
eliminates the Image B timeout problem on Hostinger where
max_execution_time killed the cron before the second request finished.

New files:
- class-open-router-image-batch.php — curl_multi orchestrator
- generate_image_batch() added to image provider interface

Pipeline refactored: prompts built upfront, single batch call, results
processed per-key. Cloudflare provider gets a sequential fallback.
Tests updated for batch API. All files under 300-line cap.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
peptiderepo
2026-04-18 21:10:54 +07:00
parent c8595e05de
commit d17c488ef3
7 changed files with 604 additions and 225 deletions

View File

@@ -83,6 +83,37 @@ interface PRAutoBlogger_Image_Provider_Interface {
*/
public function get_provider_name(): string;
/**
* Generate multiple images in parallel (or sequentially as fallback).
*
* Each entry in $requests describes one image to generate. The return array
* is indexed identically — callers can zip input and output by key.
*
* Implementations that support concurrent HTTP (e.g. curl_multi) SHOULD
* override the default sequential behaviour for a wall-clock speedup.
*
* Side effects: HTTP requests (possibly concurrent), Logger lines per image.
*
* @param array<string, array{
* prompt: string,
* width: int,
* height: int,
* options?: array{seed?: int, steps?: int, model?: string},
* }> $requests Keyed image generation requests.
*
* @return array<string, array{
* bytes: string,
* mime_type: string,
* width: int,
* height: int,
* model: string,
* seed: ?int,
* cost_usd: float,
* latency_ms: int,
* }|array{error: string}> Each key maps to either image data or an error.
*/
public function generate_image_batch( array $requests ): array;
/**
* Verify the provider credentials are present and the API is reachable.
*