Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions lib/Horde/Core/Prefs/Cache/Session.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,18 @@
/**
* Cache storage implementation using HordeSession.
*
* Reads and writes go through the modern PSR-4 {@see HordeSession}. The wire
* format diverges from values previously written through the legacy
* `Horde_Session::set()` path. Stale entries from the prior format are
* treated as missing on the first read after deploy.
* Reads go through the modern PSR-4 {@see HordeSession}. Writes invalidate
* the cached scope instead of replacing it, so the next request reloads the
* scope from storage. This avoids a write-ordering race against
* {@see \Horde\Core\Session\SessionLifecycle::shutdown()}, which mirrors
* {@see HordeSession} back into `$_SESSION` at request shutdown: a
* `store()` that ran after the mirror would never reach the persisted
* session row, leaving subsequent requests with stale prefs until the
* session was destroyed.
*
* The wire format diverges from values previously written through the
* legacy `Horde_Session::set()` path. Stale entries from the prior format
* are treated as missing on the first read after deploy.
*
* @author Michael Slusarz <slusarz@horde.org>
* @author Ralf Lang <ralf.lang@ralf-lang.de>
Expand Down Expand Up @@ -48,13 +56,20 @@ public function get($scope)
}

/**
* Invalidate the cached scope.
*
* {@see Horde_Prefs::store()} invokes this after a dirty scope has been
* written to storage. Rather than re-serializing the scope into the
* session here — which would race the lifecycle mirror at shutdown and
* could be lost before reaching the session row — drop the slot so the
* next request loads the scope fresh from storage and repopulates the
* cache on a clean read path.
*/
public function store($scope_ob)
{
$this->_session()->setScoped(
$this->_session()->removeScoped(
'horde',
self::SESS_KEY . $this->_params['user'] . '/' . $scope_ob->scope,
$scope_ob
self::SESS_KEY . $this->_params['user'] . '/' . $scope_ob->scope
);
}

Expand Down
Loading