session icon indicating copy to clipboard operation
session copied to clipboard

SessionMiddleware can not work on swoole

Open ChisWill opened this issue 4 years ago • 11 comments

Hi guys,my application run with swoole, I found I can not use SessionMiddleware because Session will be overwrite by other request. Could we add Session into attribute of request, so we can use the way $request->getAttribute(SessionInterface::class) to get Session. We also can remain old usage by add a new property when application running different env.

ChisWill avatar Aug 09 '21 06:08 ChisWill

Do you want to keep session in the worker context and not to destroy/recreate it on each request?

samdark avatar Aug 09 '21 07:08 samdark

No, I will create a new PsrRequest instance on each request and this is not my point. I mean, when we use SessionInterface as a singleton and application is running on swoole,the code

if ($requestSessionId !== null && $this->session->getId() === null) {
    $this->session->setId($requestSessionId);
}

will modify session singleton and never execute setId() again when new request come. The result is every request has same session.

ChisWill avatar Aug 09 '21 08:08 ChisWill

Wait, but $requestSessionId is obtained from request and you have different request object every time, don't you?

$requestSessionId = $this->getSessionIdFromRequest($request);

samdark avatar Aug 09 '21 09:08 samdark

Yes, request is different. But, look at the if condition if ($requestSessionId !== null && $this->session->getId() === null) { $this->session had been modified and storage in memory, so after first request the $this->session->getId() is always not null. And at the last SessionMiddleware will commitSession(), it will modify current request session id to a same value which is $this->session->getId().

ChisWill avatar Aug 09 '21 09:08 ChisWill

You're right. Any fix that comes in mind? I don't currently have Swoole environment set up :(

samdark avatar Aug 09 '21 09:08 samdark

As I mentioned in the question, we should use the code $request->getAttribute(SessionInterface::class) to get Session. I think Session depends on request, it shouldn't be a singleton instance. However, this will affect the usage of the current user, so add a property to configure? It's up to you.

ChisWill avatar Aug 09 '21 10:08 ChisWill

You're right. Any fix that comes in mind? I don't currently have Swoole environment set up :(

Make sessionId nullable.

public function setId(?string $sessionId): void
{
    $this->sessionId = $sessionId;
}

And we should add resetter in the SessionInterface::class config for those who use yiisoft/di

yiiliveext avatar Aug 10 '21 06:08 yiiliveext

I think it won't work well. In Swoole coroutine environment,suppose this situation: Even if there is only one process and the first request come and do sleep(), the process will also accept other request. At this time, the other request will modify the session, Until the sleeping request wakes up, his session had been changed. So I think every request should maintain its own session copy.

ChisWill avatar Aug 10 '21 08:08 ChisWill

  1. Added resetter config.
  2. Updated https://github.com/yiisoft/docs/blob/master/guide/en/tutorial/using-yii-with-swoole.md

@ChisWill ping us if it doesn't help please.

samdark avatar Aug 24 '21 14:08 samdark

  1. Added resetter config.
  2. Updated https://github.com/yiisoft/docs/blob/master/guide/en/tutorial/using-yii-with-swoole.md

@ChisWill ping us if it doesn't help please.

I refer to this article, but I found that in the same process session_id() always returns the same value when a new request comes. Why not use session_create_id() or other similar method?

ChisWill avatar Aug 25 '21 15:08 ChisWill

@ChisWill Php cli(on top of which swoole is run) has no idea about coroutines. So, at any given time there is 0 or 1 session in the process. And when you call session_* functions 'simultaneously' from different coroutines, you still operate on 1(or 0) session src Might be wrong tho :thinking:

alamagus avatar Jul 28 '22 11:07 alamagus