Add configurable session garbage collection (gcProbability/gcDivisor) (#258)
Make session GC probability configurable via gcProbability and gcDivisor parameters, mirroring PHP's session.gc_probability/session.gc_divisor. Exposed through both SessionManager constructor and Builder::setSession(). Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
73414d65f6
commit
5e0731f706
2 changed files with 155 additions and 7 deletions
|
|
@ -79,6 +79,10 @@ final class Builder
|
|||
|
||||
private ?SessionStoreInterface $sessionStore = null;
|
||||
|
||||
private int $gcProbability = 1;
|
||||
|
||||
private int $gcDivisor = 100;
|
||||
|
||||
private int $paginationLimit = 50;
|
||||
|
||||
private ?string $instructions = null;
|
||||
|
|
@ -336,12 +340,22 @@ final class Builder
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the session layer.
|
||||
*
|
||||
* @param int $gcProbability The numerator of the GC probability fraction (like PHP's session.gc_probability). Set to 0 to disable GC.
|
||||
* @param int $gcDivisor The denominator of the GC probability fraction (like PHP's session.gc_divisor). Probability = gcProbability/gcDivisor.
|
||||
*/
|
||||
public function setSession(
|
||||
?SessionStoreInterface $sessionStore = null,
|
||||
?SessionManagerInterface $sessionManager = null,
|
||||
int $gcProbability = 1,
|
||||
int $gcDivisor = 100,
|
||||
): self {
|
||||
$this->sessionStore = $sessionStore;
|
||||
$this->sessionManager = $sessionManager;
|
||||
$this->gcProbability = $gcProbability;
|
||||
$this->gcDivisor = $gcDivisor;
|
||||
|
||||
if (null !== $sessionManager && null !== $sessionStore) {
|
||||
throw new InvalidArgumentException('Cannot set both SessionStore and SessionManager. Set only one or the other.');
|
||||
|
|
@ -534,6 +548,8 @@ final class Builder
|
|||
$sessionManager = $this->sessionManager ?? new SessionManager(
|
||||
$this->sessionStore ?? new InMemorySessionStore(),
|
||||
$logger,
|
||||
$this->gcProbability,
|
||||
$this->gcDivisor,
|
||||
);
|
||||
|
||||
if (null !== $this->discoveryBasePath) {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
namespace Mcp\Server\Session;
|
||||
|
||||
use Mcp\Exception\InvalidArgumentException;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
use Symfony\Component\Uid\Uuid;
|
||||
|
|
@ -22,10 +23,22 @@ use Symfony\Component\Uid\Uuid;
|
|||
*/
|
||||
class SessionManager implements SessionManagerInterface
|
||||
{
|
||||
/**
|
||||
* @param int $gcProbability The probability (numerator) that GC will run on any given request. Combined with $gcDivisor to calculate the actual probability. Set to 0 to disable GC. Similar to PHP's session.gc_probability.
|
||||
* @param int $gcDivisor The divisor used with $gcProbability to calculate GC probability. The probability is gcProbability/gcDivisor (e.g. 1/100 = 1%). Similar to PHP's session.gc_divisor.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly SessionStoreInterface $store,
|
||||
private readonly LoggerInterface $logger = new NullLogger(),
|
||||
private readonly int $gcProbability = 1,
|
||||
private readonly int $gcDivisor = 100,
|
||||
) {
|
||||
if ($gcProbability < 0) {
|
||||
throw new InvalidArgumentException('gcProbability must be greater than or equal to 0.');
|
||||
}
|
||||
if ($gcDivisor < 1) {
|
||||
throw new InvalidArgumentException('gcDivisor must be greater than or equal to 1.');
|
||||
}
|
||||
}
|
||||
|
||||
public function create(): SessionInterface
|
||||
|
|
@ -54,7 +67,11 @@ class SessionManager implements SessionManagerInterface
|
|||
*/
|
||||
public function gc(): void
|
||||
{
|
||||
if (random_int(0, 100) > 1) {
|
||||
if (0 === $this->gcProbability) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (random_int(1, $this->gcDivisor) > $this->gcProbability) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue