From 6ad6dae8f1c67219ff0a6bbe6c969f2713f40f04 Mon Sep 17 00:00:00 2001 From: Duncan McClean Date: Wed, 29 Jul 2026 09:21:15 -0400 Subject: [PATCH 1/8] [6.x] Remove stale PHPStan ignore patterns (#15083) add queue timeout config to search index update job --- phpstan.dist.neon | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/phpstan.dist.neon b/phpstan.dist.neon index f15f7c292ef..516f3cd17db 100644 --- a/phpstan.dist.neon +++ b/phpstan.dist.neon @@ -48,16 +48,3 @@ parameters: identifier: staticMethod.notFound message: '#^Call to an undefined static method Statamic\\Providers\\AppServiceProvider::this\(\)\.$#' path: src/Providers/AppServiceProvider.php - - # keyByWithKey() is a public Collection macro kept for third-party/addon backward - # compatibility even though Statamic's own code no longer calls it, so its use of - # Collection's protected valueRetriever()/$items internals is left as-is rather than - # rewritten to public equivalents. - - - identifier: method.protected - message: '#^Call to protected method valueRetriever\(\) of class Illuminate\\Support\\Collection(<.*>)?\.$#' - path: src/Providers/CollectionsServiceProvider.php - - - identifier: property.protected - message: '#^Access to protected property Illuminate\\Support\\Collection::\$items\.$#' - path: src/Providers/CollectionsServiceProvider.php From c3b42e043fc92c89c2540f11f3f907cf7815021e Mon Sep 17 00:00:00 2001 From: edalzell Date: Thu, 30 Jul 2026 21:55:35 -0400 Subject: [PATCH 2/8] Allow configuring the search indexing job timeout --- PATCHES.txt | 7 +++ config/search.php | 10 +++- phpunit.xml | 26 ++++++++++ src/Search/InsertMultipleJob.php | 12 +++++ src/View/Cascade.php | 1 + tests/Search/InsertMultipleJobTest.php | 67 ++++++++++++++++++++++++++ 6 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 PATCHES.txt create mode 100644 phpunit.xml create mode 100644 tests/Search/InsertMultipleJobTest.php diff --git a/PATCHES.txt b/PATCHES.txt new file mode 100644 index 00000000000..a5a2499a18d --- /dev/null +++ b/PATCHES.txt @@ -0,0 +1,7 @@ +This file was automatically generated by Composer Patches (https://github.com/cweagans/composer-patches) +Patches applied to this directory: + +Non-revisable fields +Source: patches/11252.diff + + diff --git a/config/search.php b/config/search.php index 49b0ffdef5e..f0b3f9f2e3b 100644 --- a/config/search.php +++ b/config/search.php @@ -85,7 +85,13 @@ |-------------------------------------------------------------------------- | | Here you may configure the queue name and connection used when indexing - | documents. + | documents, along with a timeout (in seconds) for each indexing job. + | Indexing augments every item, which can take longer than your + | worker's default timeout. Leaving the timeout null defers to + | the worker's --timeout option. Any value you set should + | stay below the connection's "retry_after", otherwise a + | job that is still running will be released and then + | processed a second time. | */ @@ -93,6 +99,8 @@ 'queue_connection' => env('STATAMIC_SEARCH_QUEUE_CONNECTION'), + 'queue_timeout' => env('STATAMIC_SEARCH_QUEUE_TIMEOUT'), + /* |-------------------------------------------------------------------------- | Chunk Size diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 00000000000..2a6a07aeb8b --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,26 @@ + + + + + ./tests + + + + + + + + + + + + + diff --git a/src/Search/InsertMultipleJob.php b/src/Search/InsertMultipleJob.php index f723d688745..d0f34d5f487 100644 --- a/src/Search/InsertMultipleJob.php +++ b/src/Search/InsertMultipleJob.php @@ -15,6 +15,16 @@ class InsertMultipleJob implements ShouldQueue { use Queueable; + /** + * The number of seconds the job can run before timing out. + * + * This needs to stay a property. Queue::createObjectPayload() reads it through + * getAttributeValue($job, Timeout::class, 'timeout'), which - unlike maxTries + * and backoff - has no method_exists() fallback, so a timeout() method here + * would be silently ignored. + */ + public ?int $timeout = null; + /** * Create a new job instance. */ @@ -25,6 +35,8 @@ public function __construct( ) { $this->onConnection($connection = config('statamic.search.queue_connection', config('queue.default'))); $this->onQueue(config('statamic.search.queue', config("queue.connections.{$connection}.queue"))); + + $this->timeout = ($timeout = config('statamic.search.queue_timeout')) === null ? null : (int) $timeout; } /** diff --git a/src/View/Cascade.php b/src/View/Cascade.php index 36149fe4777..13df29aaa74 100644 --- a/src/View/Cascade.php +++ b/src/View/Cascade.php @@ -317,6 +317,7 @@ public static function config(): array 'statamic.search.defaults', 'statamic.search.queue', 'statamic.search.queue_connection', + 'statamic.search.queue_timeout', 'statamic.search.chunk_size', 'statamic.stache.watcher', 'statamic.stache.cache_store', diff --git a/tests/Search/InsertMultipleJobTest.php b/tests/Search/InsertMultipleJobTest.php new file mode 100644 index 00000000000..2a331c7434e --- /dev/null +++ b/tests/Search/InsertMultipleJobTest.php @@ -0,0 +1,67 @@ + $configured]); + + $job = new InsertMultipleJob('test', null, collect(['entry::123'])); + + $this->assertSame($expected, $job->timeout); + } + + public static function timeoutProvider() + { + return [ + 'not configured' => [null, null], + 'integer' => [300, 300], + 'string from env' => ['300', 300], + ]; + } + + #[Test, DataProvider('queueConnectionsProvider')] + public function it_uses_the_configured_queue_and_connection( + $configuredQueue, + $configuredConnection, + $defaultConnection, + $expectedJobQueue, + $expectedJobConnection + ) { + config([ + 'statamic.search.queue' => $configuredQueue, + 'statamic.search.queue_connection' => $configuredConnection, + 'queue.default' => $defaultConnection, + ]); + + $job = new InsertMultipleJob('test', null, collect(['entry::123'])); + + $this->assertSame($expectedJobQueue, $job->queue); + $this->assertSame($expectedJobConnection, $job->connection); + } + + /** + * When the config keys are null the job leaves connection/queue null rather than + * resolving them to the framework defaults, since config() only falls back to its + * second argument when a key is absent, and these keys always ship in the config + * file. A null connection/queue already means "use the default", so the outcome is + * the same - but the properties stay null. + */ + public static function queueConnectionsProvider() + { + return [ + [null, null, 'redis', null, null], + ['indexing', null, 'redis', 'indexing', null], + [null, 'sqs', 'redis', null, 'sqs'], + ['indexing', 'sqs', 'redis', 'indexing', 'sqs'], + ]; + } +} From 480b6c7c43ca644d7b0bb923930fbfd6037cd9ea Mon Sep 17 00:00:00 2001 From: edalzell Date: Thu, 30 Jul 2026 22:20:53 -0400 Subject: [PATCH 3/8] tidy --- config/search.php | 6 ------ src/Search/InsertMultipleJob.php | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/config/search.php b/config/search.php index f0b3f9f2e3b..4292708fa75 100644 --- a/config/search.php +++ b/config/search.php @@ -86,12 +86,6 @@ | | Here you may configure the queue name and connection used when indexing | documents, along with a timeout (in seconds) for each indexing job. - | Indexing augments every item, which can take longer than your - | worker's default timeout. Leaving the timeout null defers to - | the worker's --timeout option. Any value you set should - | stay below the connection's "retry_after", otherwise a - | job that is still running will be released and then - | processed a second time. | */ diff --git a/src/Search/InsertMultipleJob.php b/src/Search/InsertMultipleJob.php index d0f34d5f487..d5b3bf40e92 100644 --- a/src/Search/InsertMultipleJob.php +++ b/src/Search/InsertMultipleJob.php @@ -36,7 +36,7 @@ public function __construct( $this->onConnection($connection = config('statamic.search.queue_connection', config('queue.default'))); $this->onQueue(config('statamic.search.queue', config("queue.connections.{$connection}.queue"))); - $this->timeout = ($timeout = config('statamic.search.queue_timeout')) === null ? null : (int) $timeout; + $this->timeout = config()->integer('statamic.search.queue_timeout', null); } /** From 0d5e69a8dc736a0a4b5f1b298ae58d491719b885 Mon Sep 17 00:00:00 2001 From: Erin Dalzell Date: Thu, 30 Jul 2026 22:22:45 -0400 Subject: [PATCH 4/8] whoops --- phpunit.xml | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 phpunit.xml diff --git a/phpunit.xml b/phpunit.xml deleted file mode 100644 index 2a6a07aeb8b..00000000000 --- a/phpunit.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - ./tests - - - - - - - - - - - - - From a60fe451ce00191154fef45e122c96d2a68d8824 Mon Sep 17 00:00:00 2001 From: Erin Dalzell Date: Thu, 30 Jul 2026 22:23:31 -0400 Subject: [PATCH 5/8] Whoops --- PATCHES.txt | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 PATCHES.txt diff --git a/PATCHES.txt b/PATCHES.txt deleted file mode 100644 index a5a2499a18d..00000000000 --- a/PATCHES.txt +++ /dev/null @@ -1,7 +0,0 @@ -This file was automatically generated by Composer Patches (https://github.com/cweagans/composer-patches) -Patches applied to this directory: - -Non-revisable fields -Source: patches/11252.diff - - From 2d86c9533442efefeb41beb754033b3fe6e31988 Mon Sep 17 00:00:00 2001 From: edalzell Date: Thu, 30 Jul 2026 22:57:13 -0400 Subject: [PATCH 6/8] try this? --- src/Search/InsertMultipleJob.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Search/InsertMultipleJob.php b/src/Search/InsertMultipleJob.php index d5b3bf40e92..1f0a52bed7e 100644 --- a/src/Search/InsertMultipleJob.php +++ b/src/Search/InsertMultipleJob.php @@ -36,7 +36,7 @@ public function __construct( $this->onConnection($connection = config('statamic.search.queue_connection', config('queue.default'))); $this->onQueue(config('statamic.search.queue', config("queue.connections.{$connection}.queue"))); - $this->timeout = config()->integer('statamic.search.queue_timeout', null); + $this->timeout = config()->integer('statamic.search.queue_timeout', 0); } /** From bbed180ce826dfb92d21ac2d15445d3558c94572 Mon Sep 17 00:00:00 2001 From: edalzell Date: Thu, 30 Jul 2026 23:20:24 -0400 Subject: [PATCH 7/8] =?UTF-8?q?can=E2=80=99t=20use=20integer=20helper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Search/InsertMultipleJob.php | 4 +++- tests/Search/InsertMultipleJobTest.php | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Search/InsertMultipleJob.php b/src/Search/InsertMultipleJob.php index 1f0a52bed7e..ceeb47542f3 100644 --- a/src/Search/InsertMultipleJob.php +++ b/src/Search/InsertMultipleJob.php @@ -36,7 +36,9 @@ public function __construct( $this->onConnection($connection = config('statamic.search.queue_connection', config('queue.default'))); $this->onQueue(config('statamic.search.queue', config("queue.connections.{$connection}.queue"))); - $this->timeout = config()->integer('statamic.search.queue_timeout', 0); + if (! is_null($timeout = config('statamic.search.queue_timeout'))) { + $this->timeout = (int) $timeout; + } } /** diff --git a/tests/Search/InsertMultipleJobTest.php b/tests/Search/InsertMultipleJobTest.php index 2a331c7434e..b45aeac008e 100644 --- a/tests/Search/InsertMultipleJobTest.php +++ b/tests/Search/InsertMultipleJobTest.php @@ -23,6 +23,7 @@ public static function timeoutProvider() { return [ 'not configured' => [null, null], + 'empty env var' => ['', null], 'integer' => [300, 300], 'string from env' => ['300', 300], ]; From f83199e554bd44cee26c1f2717ec51559d1c266e Mon Sep 17 00:00:00 2001 From: edalzell Date: Fri, 31 Jul 2026 13:58:17 -0400 Subject: [PATCH 8/8] =?UTF-8?q?handle=20=E2=80=98=E2=80=99=20case?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Search/InsertMultipleJob.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Search/InsertMultipleJob.php b/src/Search/InsertMultipleJob.php index ceeb47542f3..91e806e97c8 100644 --- a/src/Search/InsertMultipleJob.php +++ b/src/Search/InsertMultipleJob.php @@ -36,7 +36,7 @@ public function __construct( $this->onConnection($connection = config('statamic.search.queue_connection', config('queue.default'))); $this->onQueue(config('statamic.search.queue', config("queue.connections.{$connection}.queue"))); - if (! is_null($timeout = config('statamic.search.queue_timeout'))) { + if (filled($timeout = config('statamic.search.queue_timeout'))) { $this->timeout = (int) $timeout; } }