Skip to content

Commit

Permalink
Merge pull request #549 from aleclarson/fix/plugin-lazyload
Browse files Browse the repository at this point in the history
fix: await the `.modules` of nested Elysia instances
  • Loading branch information
SaltyAom committed Mar 18, 2024
2 parents e2d2620 + d7d69d8 commit ff9c1d3
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 8 deletions.
23 changes: 15 additions & 8 deletions src/index.ts
Expand Up @@ -13,7 +13,7 @@ import { sucrose, sucroseTrace, type Sucrose } from './sucrose'
import { ElysiaWS, websocket } from './ws'
import type { WS } from './ws/types'

import { mergeDeep } from './utils'
import { mergeDeep, PromiseGroup } from './utils'
import {
composeHandler,
composeGeneralHandler,
Expand Down Expand Up @@ -261,9 +261,7 @@ export default class Elysia<
trace: Sucrose.TraceInference
}

private lazyLoadModules: Promise<
Elysia<any, any, any, any, any, any, any, any>
>[] = []
private promisedModules = new PromiseGroup()

constructor(config?: ElysiaConfig<BasePath, Scoped>) {
this.config = {
Expand Down Expand Up @@ -2540,7 +2538,7 @@ export default class Elysia<
}

if (plugin instanceof Promise) {
this.lazyLoadModules.push(
this.promisedModules.add(
plugin
.then((plugin) => {
if (typeof plugin === 'function') {
Expand Down Expand Up @@ -2575,7 +2573,7 @@ export default class Elysia<
if (typeof plugin === 'function') {
const instance = plugin(this as unknown as any) as unknown as any
if (instance instanceof Promise) {
this.lazyLoadModules.push(
this.promisedModules.add(
instance
.then((plugin) => {
if (plugin instanceof Elysia) {
Expand Down Expand Up @@ -2632,6 +2630,15 @@ export default class Elysia<
return instance
}

if (plugin.promisedModules.size) {
this.promisedModules.add(
plugin.modules
.then(() => this._use(plugin))
.then((x) => x.compile())
)
return this
}

const { name, seed } = plugin.config

plugin.getServer = () => this.getServer()
Expand Down Expand Up @@ -4908,7 +4915,7 @@ export default class Elysia<
}
})

Promise.all(this.lazyLoadModules).then(() => {
this.promisedModules.then(() => {
Bun?.gc(false)
})

Expand Down Expand Up @@ -4950,7 +4957,7 @@ export default class Elysia<
* Wait until all lazy loaded modules all load is fully
*/
get modules() {
return Promise.all(this.lazyLoadModules)
return Promise.resolve(this.promisedModules)
}
}

Expand Down
50 changes: 50 additions & 0 deletions src/utils.ts
Expand Up @@ -719,3 +719,53 @@ export const isNumericString = (message: string): boolean => {

return false
}

export class PromiseGroup implements PromiseLike<void> {
private root: Promise<any> | null = null
private promises: Promise<any>[] = []

constructor(public onError: (error: any) => void = console.error) {}

/**
* The number of promises still being awaited.
*/
get size() {
return this.promises.length
}

/**
* Add a promise to the group.
* @returns The promise that was added.
*/
add<T>(promise: Promise<T>) {
this.promises.push(promise)
this.root ||= this.drain()
return promise
}

private async drain() {
while (this.promises.length > 0) {
try {
await this.promises[0]
this.promises.shift()
} catch (error) {
this.onError(error)
}
}
this.root = null
}

// Allow the group to be awaited.
then<TResult1 = void, TResult2 = never>(
onfulfilled?:
| ((value: void) => TResult1 | PromiseLike<TResult1>)
| undefined
| null,
onrejected?:
| ((reason: any) => TResult2 | PromiseLike<TResult2>)
| undefined
| null
): PromiseLike<TResult1 | TResult2> {
return (this.root ?? Promise.resolve()).then(onfulfilled, onrejected)
}
}

0 comments on commit ff9c1d3

Please sign in to comment.