From 45f5d7ebf5ee13be6c7030270b57c21910187fc8 Mon Sep 17 00:00:00 2001 From: sebastianMindee <130448732+sebastianMindee@users.noreply.github.com> Date: Mon, 10 Nov 2025 13:58:18 +0100 Subject: [PATCH 01/12] :bug: fix sleep timers not properly taking floats into account --- phpcs.xml | 53 +--------------------------- src/Client.php | 8 +++-- src/ClientUtilityMixin.php | 27 +++++++++++++++ src/ClientV2.php | 6 ++-- src/Parsing/Common/Job.php | 6 +++- tests/ClientUtilityMixinTest.php | 59 ++++++++++++++++++++++++++++++++ 6 files changed, 101 insertions(+), 58 deletions(-) create mode 100644 src/ClientUtilityMixin.php create mode 100644 tests/ClientUtilityMixinTest.php diff --git a/phpcs.xml b/phpcs.xml index bd548b7a..31de617e 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -23,12 +23,6 @@ - - - - - - @@ -117,13 +111,6 @@ - - - - - - - @@ -135,16 +122,8 @@ - - - - - - - - + @@ -155,15 +134,6 @@ - - - - error - Method name "%s" must not be prefixed with an underscore to indicate visibility - - - - @@ -196,20 +166,12 @@ - - - - 0 - - - 0 - @@ -251,8 +213,6 @@ - - @@ -261,9 +221,6 @@ - - - @@ -292,14 +249,6 @@ - - - 0 - - - 0 - - diff --git a/src/Client.php b/src/Client.php index 70eb9674..3e652720 100644 --- a/src/Client.php +++ b/src/Client.php @@ -43,6 +43,8 @@ */ class Client { + use ClientUtilityMixin; + /** * Default owner for API products. * @@ -463,7 +465,7 @@ public function enqueueAndParse( ); error_log("Successfully enqueued document with job id: " . $enqueueResponse->job->id); - sleep($asyncOptions->initialDelaySec); + $this->customSleep($asyncOptions->initialDelaySec); $retryCounter = 1; $pollResults = $this->parseQueued($predictionType, $enqueueResponse->job->id, $options->endpoint); @@ -473,7 +475,7 @@ public function enqueueAndParse( } error_log("Polling server for parsing result with job id: " . $enqueueResponse->job->id); $retryCounter++; - sleep($asyncOptions->delaySec); + $this->customSleep($asyncOptions->delaySec); $pollResults = $this->parseQueued($predictionType, $enqueueResponse->job->id, $options->endpoint); } if ($pollResults->job->status != "completed") { @@ -540,7 +542,7 @@ public function parseQueued( public function loadPrediction( string $predictionType, LocalResponse $localResponse - ) { + ): AsyncPredictResponse|PredictResponse { try { $json = $localResponse->toArray(); if (isset($json['job'])) { diff --git a/src/ClientUtilityMixin.php b/src/ClientUtilityMixin.php new file mode 100644 index 00000000..6a89db19 --- /dev/null +++ b/src/ClientUtilityMixin.php @@ -0,0 +1,27 @@ + 0) { + sleep($delay); + } + if ($micros > 0) { + usleep($micros * 1_000_000); + } + } +} diff --git a/src/ClientV2.php b/src/ClientV2.php index 50d34401..b74fd081 100644 --- a/src/ClientV2.php +++ b/src/ClientV2.php @@ -14,6 +14,8 @@ */ class ClientV2 { + use ClientUtilityMixin; + /** * @var MindeeApiV2 Mindee API V2. */ @@ -96,7 +98,7 @@ public function enqueueAndGetInference( $queueId = $enqueueResponse->job->id; error_log("Successfully enqueued document with job id: " . $queueId); - sleep($pollingOptions->initialDelaySec); + $this->customSleep($pollingOptions->initialDelaySec); $retryCounter = 1; $pollResults = $this->getJob($queueId); @@ -114,7 +116,7 @@ public function enqueueAndGetInference( ". Job status: " . $pollResults->job->status ); - sleep($pollingOptions->delaySec); + $this->customSleep($pollingOptions->delaySec); $pollResults = $this->getJob($queueId); $retryCounter++; } diff --git a/src/Parsing/Common/Job.php b/src/Parsing/Common/Job.php index bd428e26..3bc4e949 100644 --- a/src/Parsing/Common/Job.php +++ b/src/Parsing/Common/Job.php @@ -37,6 +37,7 @@ class Job * @var array|null Information about an error that occurred during the job processing. */ public ?array $error; + /** * @param array $rawResponse Raw prediction array. * @throws MindeeApiException Throws if a date is faulty. @@ -58,7 +59,10 @@ public function __construct(array $rawResponse) } $this->id = $rawResponse['id']; $this->status = $rawResponse['status']; - if (array_key_exists('available_at', $rawResponse) && $rawResponse['available_at'] !== null && strtotime($rawResponse['available_at'])) { + if ( + array_key_exists('available_at', $rawResponse) && + $rawResponse['available_at'] !== null && strtotime($rawResponse['available_at']) + ) { try { $this->availableAt = new DateTimeImmutable($rawResponse['available_at']); } catch (\Exception $e) { diff --git a/tests/ClientUtilityMixinTest.php b/tests/ClientUtilityMixinTest.php new file mode 100644 index 00000000..2694b63f --- /dev/null +++ b/tests/ClientUtilityMixinTest.php @@ -0,0 +1,59 @@ +customSleep(1); + $elapsed = microtime(true) - $start; + $this->assertGreaterThanOrEqual($lowerBound, $elapsed); + $this->assertLessThanOrEqual($upperBound, $elapsed); + } + + public function testCustomSleep2Seconds(): void { + $lowerBound = 2; + $upperBound = 2.1; + + $start = microtime(true); + $this->customSleep(2); + $elapsed = microtime(true) - $start; + $this->assertGreaterThanOrEqual($lowerBound, $elapsed); + $this->assertLessThanOrEqual($upperBound, $elapsed); + } + + public function testCustomSleep1dot5Seconds(): void { + $lowerBound = 1.5; + $upperBound = 1.6; + + $start = microtime(true); + $this->customSleep(1.5); + $elapsed = microtime(true) - $start; + $this->assertGreaterThanOrEqual($lowerBound, $elapsed); + $this->assertLessThanOrEqual($upperBound, $elapsed); + } + + public function testCustomSleep0Seconds(): void { + $start = microtime(true); + $this->customSleep(0); + $elapsed = microtime(true) - $start; + $this->assertLessThanOrEqual(0.0001, $elapsed); + } + + public function testCustomSleepMinus1Seconds(): void { + $start = microtime(true); + $this->customSleep(-1); + $elapsed = microtime(true) - $start; + $this->assertLessThanOrEqual(0.0001, $elapsed); + } +} From e8058ddf62b671c94889ab00d8affa03fdfcd1ea Mon Sep 17 00:00:00 2001 From: sebastianMindee <130448732+sebastianMindee@users.noreply.github.com> Date: Mon, 10 Nov 2025 14:03:53 +0100 Subject: [PATCH 02/12] add sub-second test --- tests/ClientUtilityMixinTest.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/ClientUtilityMixinTest.php b/tests/ClientUtilityMixinTest.php index 2694b63f..62c261b5 100644 --- a/tests/ClientUtilityMixinTest.php +++ b/tests/ClientUtilityMixinTest.php @@ -21,6 +21,17 @@ public function testCustomSleep1Second(): void { $this->assertLessThanOrEqual($upperBound, $elapsed); } + public function testCustomSleep0dot33Seconds(): void { + $lowerBound = 0.33; + $upperBound = 0.43; + + $start = microtime(true); + $this->customSleep(0.33); + $elapsed = microtime(true) - $start; + $this->assertGreaterThanOrEqual($lowerBound, $elapsed); + $this->assertLessThanOrEqual($upperBound, $elapsed); + } + public function testCustomSleep2Seconds(): void { $lowerBound = 2; $upperBound = 2.1; From 47a532c5fc67bd01cc5a5afbaa277d822f0d950f Mon Sep 17 00:00:00 2001 From: sebastianMindee <130448732+sebastianMindee@users.noreply.github.com> Date: Mon, 10 Nov 2025 14:08:56 +0100 Subject: [PATCH 03/12] fix test & rename mixin --- src/Client.php | 2 +- src/ClientV2.php | 2 +- src/{ClientUtilityMixin.php => CustomSleepMixin.php} | 2 +- .../{ClientUtilityMixinTest.php => CustomSleepMixinTest.php} | 4 ++-- tests/Input/URLInputSourceTestFunctional.php | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) rename src/{ClientUtilityMixin.php => CustomSleepMixin.php} (95%) rename tests/{ClientUtilityMixinTest.php => CustomSleepMixinTest.php} (96%) diff --git a/src/Client.php b/src/Client.php index 3e652720..05ea05e1 100644 --- a/src/Client.php +++ b/src/Client.php @@ -43,7 +43,7 @@ */ class Client { - use ClientUtilityMixin; + use CustomSleepMixin; /** * Default owner for API products. diff --git a/src/ClientV2.php b/src/ClientV2.php index b74fd081..651f7ee1 100644 --- a/src/ClientV2.php +++ b/src/ClientV2.php @@ -14,7 +14,7 @@ */ class ClientV2 { - use ClientUtilityMixin; + use CustomSleepMixin; /** * @var MindeeApiV2 Mindee API V2. diff --git a/src/ClientUtilityMixin.php b/src/CustomSleepMixin.php similarity index 95% rename from src/ClientUtilityMixin.php rename to src/CustomSleepMixin.php index 6a89db19..0128ea04 100644 --- a/src/ClientUtilityMixin.php +++ b/src/CustomSleepMixin.php @@ -2,7 +2,7 @@ namespace Mindee; -trait ClientUtilityMixin +trait CustomSleepMixin { /** * Waits for a custom amount of time from either a float or an integer. diff --git a/tests/ClientUtilityMixinTest.php b/tests/CustomSleepMixinTest.php similarity index 96% rename from tests/ClientUtilityMixinTest.php rename to tests/CustomSleepMixinTest.php index 62c261b5..5e8cc0cf 100644 --- a/tests/ClientUtilityMixinTest.php +++ b/tests/CustomSleepMixinTest.php @@ -6,9 +6,9 @@ * Custom delay tests. * Note: Timers are purposefully kept loose due to frequent CI issues. */ -class ClientUtilityMixinTest extends TestCase +class CustomSleepMixinTest extends TestCase { - use Mindee\ClientUtilityMixin; + use Mindee\CustomSleepMixin; public function testCustomSleep1Second(): void { $lowerBound = 1; diff --git a/tests/Input/URLInputSourceTestFunctional.php b/tests/Input/URLInputSourceTestFunctional.php index e18f0c8c..37524f20 100644 --- a/tests/Input/URLInputSourceTestFunctional.php +++ b/tests/Input/URLInputSourceTestFunctional.php @@ -18,7 +18,7 @@ protected function setUp(): void $this->client = new Client(); $this->outputFilePath = (getenv('GITHUB_WORKSPACE') ?: ".") . "/tests/resources/output/"; - $this->referenceFilePath = "https://github.com/mindee/client-lib-test-data/blob/main/products/invoice_splitter/invoice_5p.pdf?raw=true"; + $this->referenceFilePath = "https://github.com/mindee/client-lib-test-data/blob/main/v1/products/invoice_splitter/invoice_5p.pdf?raw=true"; } public static function tearDownAfterClass(): void From 17d0cce5de97259fe02e76f91628acd2dfadb52e Mon Sep 17 00:00:00 2001 From: sebastianMindee <130448732+sebastianMindee@users.noreply.github.com> Date: Mon, 10 Nov 2025 14:16:36 +0100 Subject: [PATCH 04/12] fix typo --- src/CustomSleepMixin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CustomSleepMixin.php b/src/CustomSleepMixin.php index 0128ea04..a157e6cc 100644 --- a/src/CustomSleepMixin.php +++ b/src/CustomSleepMixin.php @@ -18,7 +18,7 @@ protected static function customSleep(float|int $delay): void $seconds = intval($delay); $micros = $delay - $seconds; if ($seconds > 0) { - sleep($delay); + sleep($seconds); } if ($micros > 0) { usleep($micros * 1_000_000); From ab7adb8a62e07b85b7c55bef9993a62faab402a4 Mon Sep 17 00:00:00 2001 From: sebastianMindee <130448732+sebastianMindee@users.noreply.github.com> Date: Mon, 10 Nov 2025 14:29:17 +0100 Subject: [PATCH 05/12] switch to stricter conversion for microseconds --- src/CustomSleepMixin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CustomSleepMixin.php b/src/CustomSleepMixin.php index a157e6cc..eec88256 100644 --- a/src/CustomSleepMixin.php +++ b/src/CustomSleepMixin.php @@ -16,7 +16,7 @@ protected static function customSleep(float|int $delay): void } $seconds = intval($delay); - $micros = $delay - $seconds; + $micros = (int) round(((float) $delay - $seconds) * 1_000_000); if ($seconds > 0) { sleep($seconds); } From 3c0e7e9b3c3d4302169b713f3bafa1345424e6af Mon Sep 17 00:00:00 2001 From: sebastianMindee <130448732+sebastianMindee@users.noreply.github.com> Date: Mon, 10 Nov 2025 15:07:32 +0100 Subject: [PATCH 06/12] fix wrong computation --- src/CustomSleepMixin.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CustomSleepMixin.php b/src/CustomSleepMixin.php index eec88256..9ade2493 100644 --- a/src/CustomSleepMixin.php +++ b/src/CustomSleepMixin.php @@ -16,12 +16,12 @@ protected static function customSleep(float|int $delay): void } $seconds = intval($delay); - $micros = (int) round(((float) $delay - $seconds) * 1_000_000); + $micros = (int) round(($delay - (float) $seconds) * 1_000_000); if ($seconds > 0) { sleep($seconds); } if ($micros > 0) { - usleep($micros * 1_000_000); + usleep($micros); } } } From cfc427ff04b77af43e0b1e885dfc853d9395e5bd Mon Sep 17 00:00:00 2001 From: sebastianMindee <130448732+sebastianMindee@users.noreply.github.com> Date: Mon, 10 Nov 2025 15:15:04 +0100 Subject: [PATCH 07/12] switch to time_nanosleep --- src/CustomSleepMixin.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/CustomSleepMixin.php b/src/CustomSleepMixin.php index 9ade2493..f723dffb 100644 --- a/src/CustomSleepMixin.php +++ b/src/CustomSleepMixin.php @@ -16,12 +16,7 @@ protected static function customSleep(float|int $delay): void } $seconds = intval($delay); - $micros = (int) round(($delay - (float) $seconds) * 1_000_000); - if ($seconds > 0) { - sleep($seconds); - } - if ($micros > 0) { - usleep($micros); - } + $nanoseconds = abs((float) $seconds - $delay); + time_nanosleep($seconds, $nanoseconds * 1_000_000_000); } } From c8400e30db17e3c6ee34022130b0f70f6c1782c6 Mon Sep 17 00:00:00 2001 From: sebastianMindee <130448732+sebastianMindee@users.noreply.github.com> Date: Mon, 10 Nov 2025 15:51:58 +0100 Subject: [PATCH 08/12] fix windows test --- src/CustomSleepMixin.php | 2 +- tests/CustomSleepMixinTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CustomSleepMixin.php b/src/CustomSleepMixin.php index f723dffb..c458012e 100644 --- a/src/CustomSleepMixin.php +++ b/src/CustomSleepMixin.php @@ -16,7 +16,7 @@ protected static function customSleep(float|int $delay): void } $seconds = intval($delay); - $nanoseconds = abs((float) $seconds - $delay); + $nanoseconds = (int) abs((float) $seconds - $delay); time_nanosleep($seconds, $nanoseconds * 1_000_000_000); } } diff --git a/tests/CustomSleepMixinTest.php b/tests/CustomSleepMixinTest.php index 5e8cc0cf..e63fed13 100644 --- a/tests/CustomSleepMixinTest.php +++ b/tests/CustomSleepMixinTest.php @@ -22,7 +22,7 @@ public function testCustomSleep1Second(): void { } public function testCustomSleep0dot33Seconds(): void { - $lowerBound = 0.33; + $lowerBound = 0.32; // Note: Windows struggles to run this one consistently when < 1 second $upperBound = 0.43; $start = microtime(true); From e60363ff780a5d259abd5ac9cc0b8791fdc80bf4 Mon Sep 17 00:00:00 2001 From: sebastianMindee <130448732+sebastianMindee@users.noreply.github.com> Date: Mon, 10 Nov 2025 15:57:48 +0100 Subject: [PATCH 09/12] fix typing --- src/CustomSleepMixin.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CustomSleepMixin.php b/src/CustomSleepMixin.php index c458012e..7ddbeaa1 100644 --- a/src/CustomSleepMixin.php +++ b/src/CustomSleepMixin.php @@ -16,7 +16,7 @@ protected static function customSleep(float|int $delay): void } $seconds = intval($delay); - $nanoseconds = (int) abs((float) $seconds - $delay); - time_nanosleep($seconds, $nanoseconds * 1_000_000_000); + $nanoseconds = abs($seconds - (float) $delay); + time_nanosleep($seconds, (int) ($nanoseconds * 1_000_000_000)); } } From 2991c994ae1652bc7ae327b37df20b82e51a8532 Mon Sep 17 00:00:00 2001 From: sebastianMindee <130448732+sebastianMindee@users.noreply.github.com> Date: Mon, 10 Nov 2025 16:08:37 +0100 Subject: [PATCH 10/12] fix windows-related timing issues --- src/CustomSleepMixin.php | 6 ++++++ tests/CustomSleepMixinTest.php | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/CustomSleepMixin.php b/src/CustomSleepMixin.php index 7ddbeaa1..27f5199e 100644 --- a/src/CustomSleepMixin.php +++ b/src/CustomSleepMixin.php @@ -17,6 +17,12 @@ protected static function customSleep(float|int $delay): void $seconds = intval($delay); $nanoseconds = abs($seconds - (float) $delay); + if ( + strtoupper(substr(PHP_OS_FAMILY, 0, 7)) === 'WINDOWS' && + $nanoseconds > 0.000000001 + ) { + usleep(100000); + } time_nanosleep($seconds, (int) ($nanoseconds * 1_000_000_000)); } } diff --git a/tests/CustomSleepMixinTest.php b/tests/CustomSleepMixinTest.php index e63fed13..5e8cc0cf 100644 --- a/tests/CustomSleepMixinTest.php +++ b/tests/CustomSleepMixinTest.php @@ -22,7 +22,7 @@ public function testCustomSleep1Second(): void { } public function testCustomSleep0dot33Seconds(): void { - $lowerBound = 0.32; // Note: Windows struggles to run this one consistently when < 1 second + $lowerBound = 0.33; $upperBound = 0.43; $start = microtime(true); From 4fb3037a7e2fc684b7720a936da295df9f429188 Mon Sep 17 00:00:00 2001 From: sebastianMindee <130448732+sebastianMindee@users.noreply.github.com> Date: Mon, 10 Nov 2025 16:12:37 +0100 Subject: [PATCH 11/12] fix windows-related timing issues... again --- src/CustomSleepMixin.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/CustomSleepMixin.php b/src/CustomSleepMixin.php index 27f5199e..c152e120 100644 --- a/src/CustomSleepMixin.php +++ b/src/CustomSleepMixin.php @@ -18,10 +18,9 @@ protected static function customSleep(float|int $delay): void $seconds = intval($delay); $nanoseconds = abs($seconds - (float) $delay); if ( - strtoupper(substr(PHP_OS_FAMILY, 0, 7)) === 'WINDOWS' && - $nanoseconds > 0.000000001 + strtoupper(substr(PHP_OS_FAMILY, 0, 7)) === 'WINDOWS' ) { - usleep(100000); + usleep(100_000); } time_nanosleep($seconds, (int) ($nanoseconds * 1_000_000_000)); } From ec7ee961356e9cde1dc9d4516645f94702ee12cc Mon Sep 17 00:00:00 2001 From: sebastianMindee <130448732+sebastianMindee@users.noreply.github.com> Date: Mon, 10 Nov 2025 16:16:09 +0100 Subject: [PATCH 12/12] reduce windows fix delay timer --- src/CustomSleepMixin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CustomSleepMixin.php b/src/CustomSleepMixin.php index c152e120..9c7cd0cd 100644 --- a/src/CustomSleepMixin.php +++ b/src/CustomSleepMixin.php @@ -20,7 +20,7 @@ protected static function customSleep(float|int $delay): void if ( strtoupper(substr(PHP_OS_FAMILY, 0, 7)) === 'WINDOWS' ) { - usleep(100_000); + usleep(1000); } time_nanosleep($seconds, (int) ($nanoseconds * 1_000_000_000)); }