From 83511c78d8bde138248800d695d9974d92024e1c Mon Sep 17 00:00:00 2001 From: Yaroslav Nahirnyi Date: Tue, 26 Mar 2024 17:35:59 +0200 Subject: [PATCH] fix: Added $minChunkNumber to chunkWithQueue mixin (#29) * misc: Added $minChunkNumber to chunkWithQueue mixin * fix: Fixed phpstan * fix: Fixed phpstan --- phpstan.neon | 2 +- src/Jobs/HandleChunkJob.php | 1 - src/Mixins/EloquentBuilderMixin.php | 15 ++++++++++++++- src/Settings/ChunkWithQueue/QueryOptions.php | 5 +++-- tests/EloquentBuilderMixin/ChunkWithQueueTest.php | 8 +++++--- 5 files changed, 23 insertions(+), 8 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index 9c084fe..ef6f78c 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -28,7 +28,7 @@ parameters: message: '#Call to protected method .+#i' path: '*Mixin.php' - - message: '#Access to .* property .+Mixin::.+#i' + message: '#Access to .* property .+Mixin.*::.+#i' path: '*Mixin.php' - message: '#Method .+Mixin::.+ invoked with \d parameters, \d required.#i' diff --git a/src/Jobs/HandleChunkJob.php b/src/Jobs/HandleChunkJob.php index 5b5141c..7c19ac9 100644 --- a/src/Jobs/HandleChunkJob.php +++ b/src/Jobs/HandleChunkJob.php @@ -55,7 +55,6 @@ public function handle(): void : new SimpleQueuedChunkHandler($this->handler->getHandler()); if (is_callable($handler)) { - /* @phpstan-ignore-next-line Refactor handlers to fix these */ $handler($items); } else { /* @phpstan-ignore-next-line Refactor handlers to fix these */ diff --git a/src/Mixins/EloquentBuilderMixin.php b/src/Mixins/EloquentBuilderMixin.php index b5910b4..3c69401 100644 --- a/src/Mixins/EloquentBuilderMixin.php +++ b/src/Mixins/EloquentBuilderMixin.php @@ -282,11 +282,24 @@ public function chunkWithQueue(): callable ->first($settings->queryOptions->keyName) )->{$settings->queryOptions->attributeKeyName}; + $minKeyValue = optional( + DB::query() + ->fromSub( + ($settings->queryOptions->getMinKeyValueFromNewModelQuery ? $this->getModel()->newQuery() : $this->clone()) + ->toBase() + ->orderBy($settings->queryOptions->keyName) + ->limit(1), + $this->getModel()->getTable() + ) + ->first($settings->queryOptions->keyName) + )->{$settings->queryOptions->attributeKeyName} ?? 1; + if (!$maxKeyValue) { return true; } $maxChunkNumber = (int) ceil($maxKeyValue / $settings->chunkOptions->pieceSize); + $minChunkNumber = max((int) floor($minKeyValue / $settings->chunkOptions->pieceSize), 1); $params = new ChunkParams( $handler, @@ -299,7 +312,7 @@ public function chunkWithQueue(): callable $builder = new SerializableBuilder($query); - for ($chunkNumber = 1; $chunkNumber <= $maxChunkNumber; $chunkNumber++) { + for ($chunkNumber = $minChunkNumber; $chunkNumber <= $maxChunkNumber; $chunkNumber++) { dispatch(new GenerateChunksJob($builder, $params, $chunkNumber)) ->onQueue($settings->queueOptions->pieceQueue) ->delay($settings->queueOptions->delay ? $settings->queueOptions->delay * ($chunkNumber - 1) : null); diff --git a/src/Settings/ChunkWithQueue/QueryOptions.php b/src/Settings/ChunkWithQueue/QueryOptions.php index 2744e90..cc5c15d 100644 --- a/src/Settings/ChunkWithQueue/QueryOptions.php +++ b/src/Settings/ChunkWithQueue/QueryOptions.php @@ -16,6 +16,7 @@ public function __construct( public readonly string $keyName, string $attributeKeyName = null, public readonly bool $getMaxKeyValueFromNewModelQuery = false, + public readonly bool $getMinKeyValueFromNewModelQuery = false, ) { $this->attributeKeyName = $attributeKeyName ?? Str::contains($this->keyName, '.') ? trim(explode('.', $this->keyName)[1], '\'"') @@ -27,8 +28,8 @@ public static function defaultInstance(): self return new self('id'); } - public static function defaultInstanceWithMaxIdFromBaseQuery(): self + public static function defaultInstanceFromWholeTableQuery(): self { - return new self('id', null, true); + return new self('id', null, true, true); } } diff --git a/tests/EloquentBuilderMixin/ChunkWithQueueTest.php b/tests/EloquentBuilderMixin/ChunkWithQueueTest.php index f89082a..7387e0c 100644 --- a/tests/EloquentBuilderMixin/ChunkWithQueueTest.php +++ b/tests/EloquentBuilderMixin/ChunkWithQueueTest.php @@ -106,27 +106,29 @@ public function testMultipleJobsWithTableNameInQuerySettingsSuccess(): void Queue::assertPushed(GenerateChunksJob::class, 2); } - public function testWithMaxIdFromBaseQuery(): void + public function testGenerateJobsForWholeQuery(): void { Queue::fake(); + $this->generateTestModel(); $this->generateTestModel(fn (TestStubFactory $factory) => $factory->hasChildren(TestStubFactory::new())); $this->generateTestModel(); $settings = ChunkWithQueueSettings::defaultSettings(); $settings->chunkOptions->chunkSize = 1; $settings->chunkOptions->pieceSize = 1; - $settings->queryOptions = QueryOptions::defaultInstanceWithMaxIdFromBaseQuery(); + $settings->queryOptions = QueryOptions::defaultInstanceFromWholeTableQuery(); TestStub::query()->whereHas('children')->chunkWithQueue(HandlerStub::class, $settings); - Queue::assertPushed(GenerateChunksJob::class, 3); + Queue::assertPushed(GenerateChunksJob::class, 4); } public function testWithMaxIdFromGivenQuery(): void { Queue::fake(); + $this->generateTestModel(); $this->generateTestModel(fn (TestStubFactory $factory) => $factory->hasChildren(TestStubFactory::new())); $this->generateTestModel();