Skip to content

Commit

Permalink
chore(docs): update
Browse files Browse the repository at this point in the history
  • Loading branch information
razshare committed Apr 1, 2024
1 parent 3392f2b commit b0652f0
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 12 deletions.
62 changes: 61 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,64 @@ If the client doesn't hold a session id cookie, then it means it has no session,
If the client does have a session id but is expired, then the relative session is immediately destroyed, and a new session is created.\
This new session doesn't contain any of the old session's data.

Finally, if the client has a valid session id cookie, the relative session is retrieved.
Finally, if the client has a valid session id cookie, the relative session is retrieved.
\
\
Starting a session should always succeed, wether it is by creating a new session or retrieving an existing one.

# Flush

As explained above, in the [lifetime section](#lifetime), clients that present an expired session id have their sessions destroyed immediately.

However, this mechanism assumes clients are very active.\
Sometimes clients abandon their sessions and never awaken them again.

This can be a problem.

Even though these sessions are not active, they will still use some memory.\
They must be destroyed one way or another.

**You can use `destroy()`**
```js
// src/routes/session/destroy/+server.js
import { session } from 'sveltekit-server-session'

/**
*
* @param {number} milliseconds
* @returns {Promise<void>}
*/
function delay(milliseconds) {
return new Promise(function start(resolve) {
setTimeout(resolve, milliseconds)
})
}

export async function GET({ cookies }) {
const {
error,
value: { destroy },
} = await session.start({ cookies })

if (error) {
return new Response(error.message, { status: 500 })
}

await destroy()

await delay(3000)

return new Response('Session destroyed.')
}
```
to destroy each session manually.

> [!NOTE]
> For example this may be useful to invoke
> when clicking a _logout_ button.

# Custom behavior

You can customize your session manager's behavior with `session.setOperations()`.

20 changes: 11 additions & 9 deletions src/lib/session.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ function create({ id, data }) {
const remaining = expiresAtUnix - now
return remaining >= 0 ? remaining : 0
},
async destroy() {
const destroyAttempt = await _interface.delete(id)
if (destroyAttempt.error) {
return destroyAttempt
}
return ok()
},
response(body, init) {
const cookieName = encodeURI(sessionKey)
const cookieValue = encodeURI(id)
Expand Down Expand Up @@ -251,23 +258,18 @@ export const session = {
return
}
flushing = true
const promisses = []
/**
* @type {Array<string>}
* @type {Array<Promise<import('./types').Unsafe<void>>>}
*/
const toBeRemoved = []
const destructors = []
for (const [, session] of map) {
if (isValid({ id: session.id })) {
continue
}
toBeRemoved.push(session.id)
}

for (const id of toBeRemoved) {
promisses.push(_interface.delete(id))
destructors.push(session.destroy())
}

await Promise.all(promisses)
await Promise.all(destructors)
flushing = false
},
}
Expand Down
6 changes: 6 additions & 0 deletions src/lib/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,15 @@ export {}
* @property {number} createdUnix Unix timestamp indicating the creation date of the session (readonly).
* @property {number} expiresAtUnix Unix timestamp of when the session will expire (readonly).
* @property {GetRemainingSeconds} getRemainingSeconds Get the seconds remaining before the session expires.
* @property {Destroy} destroy Get the seconds remaining before the session expires.
* @property {ResponseCreator} response Create a new `Response` with the required headers for managing the session.
*/

/**
* @callback Destroy
* @returns {Promise<Unsafe<void>>}
*/

/**
* @callback GetRemainingSeconds
* @returns {number} The seconds remaining before the session expires.
Expand Down
4 changes: 2 additions & 2 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@
let sending = false
onMount(async function start() {
const response = await fetch('/session/counter/get')
const response = await fetch('/session/quote/get')
text = await response.text()
ready = true
})
async function set() {
sending = true
await fetch('/session/counter/update', { method: 'PUT', body: text })
await fetch('/session/quote/update', { method: 'PUT', body: text })
sending = false
}
</script>
Expand Down
37 changes: 37 additions & 0 deletions src/routes/destroy/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<style>
.content {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
overflow-x: hidden;
padding: 1rem;
display: grid;
justify-content: center;
align-content: center;
}
</style>

<script>
let sending = false
let count = 0
async function destroy() {
sending = true
await fetch('/session/destroy')
count++
sending = false
}
</script>

<div class="content">
<button disabled={sending} on:mouseup={destroy}>
<span>Destroy</span>
</button>
{#if sending}
<span>Destroying session...</span>
{:else if count > 0}
<span>Done.</span>
{/if}
</div>
29 changes: 29 additions & 0 deletions src/routes/session/destroy/+server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { session } from '$lib/session'

/**
*
* @param {number} milliseconds
* @returns {Promise<void>}
*/
function delay(milliseconds) {
return new Promise(function start(resolve) {
setTimeout(resolve, milliseconds)
})
}

export async function GET({ cookies }) {
const {
error,
value: { destroy },
} = await session.start({ cookies })

if (error) {
return new Response(error.message, { status: 500 })
}

await destroy()

await delay(3000)

return new Response('Session destroyed.')
}

0 comments on commit b0652f0

Please sign in to comment.