Skip to content

Commit

Permalink
feat: use AsyncLocalStorageFallback when AsyncLocalStorage is not ava…
Browse files Browse the repository at this point in the history
…ilable
  • Loading branch information
usualoma committed May 4, 2024
1 parent 4e41724 commit e90fa80
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 6 deletions.
4 changes: 2 additions & 2 deletions src/server/components/has-islands.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { IMPORTING_ISLANDS_ID } from '../../constants.js'
import { contextStorage } from '../context-storage.js'
import { getStorageSync } from '../context-storage.js'

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const HasIslands = ({ children }: { children: any }): any => {
const c = contextStorage.getStore()
const c = getStorageSync().getStore()
if (!c) {
throw new Error('No context found')
}
Expand Down
40 changes: 38 additions & 2 deletions src/server/context-storage.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,39 @@
import { AsyncLocalStorage } from 'node:async_hooks'
import type { AsyncLocalStorage } from 'node:async_hooks'
import type { Context } from 'hono'
export const contextStorage = new AsyncLocalStorage<Context>()

class AsyncLocalStorageFallback<T> {
store: T | undefined
getStore() {
return this.store
}
async run(store: T, callback: () => Promise<void>) {
if (this.store) {
throw new Error('Already running')
}

this.store = store
await callback()
this.store = undefined
}
}

let contextStorage: AsyncLocalStorage<Context> | undefined
export const getStorage = async () => {
if (!contextStorage) {
try {
const { AsyncLocalStorage } = await import('node:async_hooks')
contextStorage = new AsyncLocalStorage<Context>()
} catch (e) {
contextStorage =
new AsyncLocalStorageFallback<Context>() as unknown as AsyncLocalStorage<Context>
}
}
return contextStorage
}

export const getStorageSync = () => {
if (!contextStorage) {
throw new Error('No context found')
}
return contextStorage
}
5 changes: 3 additions & 2 deletions src/server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
listByDirectory,
sortDirectoriesByDepth,
} from '../utils/file.js'
import { contextStorage } from './context-storage.js'
import { getStorage } from './context-storage.js'

const NOTFOUND_FILENAME = '_404.tsx'
const ERROR_FILENAME = '_error.tsx'
Expand Down Expand Up @@ -64,8 +64,9 @@ export const createApp = <E extends Env>(options: BaseServerOptions<E>): Hono<E>
const trailingSlash = options.trailingSlash ?? false

// Share context by AsyncLocalStorage
const getStoragePromise = getStorage()
app.use(async function ShareContext(c, next) {
await contextStorage.run(c, () => next())
await (await getStoragePromise).run(c, () => next())
})

if (options.init) {
Expand Down

0 comments on commit e90fa80

Please sign in to comment.