Skip to content

[6.x] Reset memoized Stache state when an Octane request arrives - #15858

Open
DanielDarrenJones wants to merge 2 commits into
statamic:6.xfrom
DanielDarrenJones:fix/6x-octane-store-reset
Open

DanielDarrenJones wants to merge 2 commits into
statamic:6.xfrom
DanielDarrenJones:fix/6x-octane-store-reset

Conversation

@DanielDarrenJones

Copy link
Copy Markdown
Contributor

Fixes #15857.

The Stache's stores are made when the app boots, so under Octane a worker uses the same ones for every request it handles. Each store memoizes its paths the first time it's used. An entry that another process creates or renames afterwards isn't in that list, so the worker can't find it and its page is a 404 until the worker is reloaded.

Queue workers had the same problem, and the stores and indexes are told to forget what they've memoized before each job (resetMemoizedStateBetweenJobs()). This does the same when an Octane request arrives.

  • The event is listened for by name, since Octane isn't a dependency and may not be installed.
  • The stores are the ones made at boot. The indexes are taken from the current container, because Octane handles each request in its own copy of it.
  • Unlike the between-jobs reset there's no check for what kind of process this is: the event is only fired by Octane.

Checked

Through Octane's own Laravel\Octane\Worker class, with a second PHP process doing the writes (the script is in the issue):

Before After A fresh PHP process
An article created by another process 404 200 200
Its new URL after another process changes its slug 404 200 200
Its old URL 404 404
Its URL after another process deletes it 404 404

This drives the worker in one process rather than through a running FrankenPHP, Swoole or RoadRunner server.

Cost

Each request reads the paths of the stores it uses from the cache again, as a request under PHP-FPM does. On a site of 358 entries, three pages served 30 times each through the worker, alternating before and after for three rounds, came out within 2% of each other either way (around 287 ms, 212 ms and 258 ms). I haven't measured it on a large site, where the lists are longer.

Not covered

With the Stache watcher on, a store still only checks for changed files once ($fileChangesHandled), so a file edited outside Statamic isn't picked up by a running worker. That's the same for queue workers today and is left alone here.

Tests

it_resets_memoized_store_and_index_state_when_an_octane_request_arrives in Stache\ServiceProviderTest, next to the between-jobs tests. It fires the event by name, and fails without the change.

The stores are made when the app boots, so an Octane worker uses the same ones
for every request. They were only told to forget what they'd memoized between
queued jobs, so a worker never saw an entry that another process created or
renamed.
@DanielDarrenJones
DanielDarrenJones marked this pull request as ready for review November 12, 2026 00:10

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Entries created or renamed by another process 404 in a long-lived Octane worker

1 participant