-
-
Notifications
You must be signed in to change notification settings - Fork 21
Refactor session handling #48
base: main
Are you sure you want to change the base?
Conversation
- Move newSessionIfModified logic to dedicated method - Use deep equal comparison to watch changes of the context session
Hey @interpretor! Thanks for the contribution - usually I would prefer to merge the PRs individually with one change (feat, fix, docs, ...) per PR. Is there a strong reason to doing all of this in one go? |
Hey @BracketJohn, if you want you can merge the PRs #36, #41 and #47 individually and then merge this PR on top, that should work. The restructuring of the session handling here bases on the individual PRs, so I had to merge them in my dev branch first. It also removes redundant hooks ( |
const session = await ensureSession(event) | ||
// 2. Save current state of the session | ||
const oldSession = { ...session } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest to move copying logic this into the getSession
so ensureSession
either creates a new one or returns a copy of the old
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moving the copying logic to getSession
would not work, as the oldSession
object has to be different from the one saved to the event context. We could return a copy of the session after saving a reference to the event context in ensureSession
.
// @ts-ignore Replacing res.end() will lead to type checking error | ||
res.end = async (chunk: any, encoding: BufferEncoding) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overwriting standard node js methods is obviously not recommended. Is there a better way doing that?
- What is the exact type error that is thrown here?
- Also, I'm not sure if
res.end
can be async, since it is expected to returnthis
according to the docs I don't think it's being awaited. Was it at least tested with long timeouts?- also the express session doesn't make it async
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that there is no alternative, as already mentioned in #41. There is no hook at the end of all event handlers, and no event that fires just before sending the response.
res.end
returns always aServerResponse
, and here it returns aPromise<ServerResponse>
. Also there are multiple overloads, andres.end
also accepts a callback. In express session this leads to problems, so they decided to ditch the callback, as it is very rarely used.- The types don't allow
res.end
being async, but it works perfectly. I tested with long timeouts with various conditions, so it must be awaited, but I didn't check it in the node source code.
// @ts-ignore Replacing res.end() will lead to type checking error | ||
res.end = async (chunk: any, encoding: BufferEncoding) => { | ||
await middleWare() | ||
return end.call(res, chunk, encoding) as ServerResponse |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you need to typecast it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
res.end.call()
returns any
, not ServerResponse
const newSession = event.context.session as Session | ||
const storedSession = await getSession(event) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's get confusing here, as you got too many session names: session
, oldSession
, newSession
and storedSession
(where oldSession
is in actuality can be newly created or existing one)
Please propose a better naming for those
README.md
Outdated
// Sessions are saved to the store, even if they were never modified during the request | ||
resave: true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Same here, you need to provide better explanation
- Also
expressjs/session
recommends false by default
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
expressjs/session
recommends false, but the current behavior of @sidebase/nuxt-session
is true, so I've chosen to not change the default behavior. It is also recommended to set resave
to false.
We can change it if you want.
Co-authored-by: valia fetisov <[email protected]>
…xt-session into refactor-session-handling
Is there any help I can provide on this to help push it through? Currently the library clears sessions if any network requests happen directly after the session is saved (i.e a redirect) as the |
@zoey-kaiser @BracketJohn how does this look to you? |
Hey @greym0uth 👋 Thanks for reaching out + pushing this. I agree that having this PR merged would be very valuable. As it is quite a complex change and @interpretor + @valiafetisov have already done quite a lot of iterations, I do want @valiafetisov to finish his review and approve. Then we can merge without further reviews from my side + do a release right away. @valiafetisov can you look into this on Monday or Tuesday to see if there are any major blockers left? Thanks @greym0uth and @interpretor for your patience - we've sadly been super occupied with other libs, modules, community work, ... :/ |
Sadly I've been experiencing issues while testing with this PR and SSR because of making |
The code looks good except for the hack on which it depends. This line:
Conclusion: I don't recommend merging this PR since it uses undocumented node.js behaviour, which might break core functionality of this package. Looking forward to the refactoring hinted by @interpretor to reevaluate this intermediate conclusion ✨ |
What if instead of overriding it with a async function we expose an async |
This combines #36, #41 and #47 and refactors the handling of (modified) session.
Instead of listening to
event.res.on('finish')
, it uses theresEndProxy
from #41 to save changes made to the session.This has a few advantages, because it is called at the very end of all event handlers, but before sending the response to the client:
saveUninitialized
.To reduce storage operations, I extracted the
setStorageSession()
fromnewSession()
and createdsetSession()
.newSession()
will now just initialize a new session and publish it at theevent.context
, but will be saved only when every event handler has finished (with callingsetSession()
). Before,setStorageSession()
has been called twice: First while creating a new Session instance, then at theevent.res.on('finish')
event handler.