@getvision/server 0.3.0 → 0.3.1-3b055ce-develop

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getvision/server",
3
- "version": "0.3.0",
3
+ "version": "0.3.1-3b055ce-develop",
4
4
  "type": "module",
5
5
  "description": "Vision Server - Meta-framework with built-in observability, pub/sub, and type-safe APIs",
6
6
  "exports": {
package/src/event-bus.ts CHANGED
@@ -203,6 +203,15 @@ export class EventBus {
203
203
  host: 'localhost',
204
204
  port: 6379,
205
205
  }
206
+ const workerKey = `${eventName}-handler`
207
+
208
+ // Close existing worker if it exists
209
+ const existingWorker = this.workers.get(workerKey)
210
+ if (existingWorker) {
211
+ void existingWorker.close().catch(() => {})
212
+ this.workers.delete(workerKey)
213
+ }
214
+
206
215
  const worker = new Worker(
207
216
  eventName,
208
217
  async (job) => {
@@ -219,7 +228,7 @@ export class EventBus {
219
228
  }
220
229
  )
221
230
 
222
- this.workers.set(`${eventName}-${Date.now()}`, worker)
231
+ this.workers.set(workerKey, worker)
223
232
 
224
233
  // Listen to queue events
225
234
  if (!this.queueEvents.has(eventName)) {
@@ -266,6 +275,15 @@ export class EventBus {
266
275
  host: 'localhost',
267
276
  port: 6379,
268
277
  }
278
+ const cronWorkerKey = `${cronName}-handler`
279
+
280
+ // Close existing cron worker if it exists
281
+ const existingCronWorker = this.workers.get(cronWorkerKey)
282
+ if (existingCronWorker) {
283
+ void existingCronWorker.close().catch(() => {})
284
+ this.workers.delete(cronWorkerKey)
285
+ }
286
+
269
287
  const worker = new Worker(
270
288
  cronName,
271
289
  async (job) => {
@@ -287,7 +305,7 @@ export class EventBus {
287
305
  }
288
306
  )
289
307
 
290
- this.workers.set(`${cronName}-${Date.now()}`, worker)
308
+ this.workers.set(cronWorkerKey, worker)
291
309
 
292
310
  // Listen to cron job events
293
311
  if (!this.queueEvents.has(cronName)) {
package/src/vision-app.ts CHANGED
@@ -624,6 +624,10 @@ export class Vision<
624
624
  if (this.shuttingDown) return
625
625
  this.shuttingDown = true
626
626
  console.log('🛑 Shutting down...')
627
+ try {
628
+ // Clear AsyncLocalStorage to prevent memory leaks
629
+ visionContext.disable()
630
+ } catch {}
627
631
  try {
628
632
  if (this.bunServer && typeof this.bunServer.stop === 'function') {
629
633
  try { this.bunServer.stop() } catch {}
@@ -632,6 +636,7 @@ export class Vision<
632
636
  } catch {}
633
637
  try { stopDrizzleStudio() } catch {}
634
638
  try { await this.eventBus.close() } catch {}
639
+ try { eventRegistry.clear() } catch {}
635
640
  }
636
641
 
637
642
  const wrappedCleanup = async () => {
@@ -641,6 +646,17 @@ export class Vision<
641
646
  process.once('SIGINT', wrappedCleanup)
642
647
  process.once('SIGTERM', wrappedCleanup)
643
648
  try { process.once('SIGQUIT', wrappedCleanup) } catch {}
649
+
650
+ // Bun hot-reload: ensure resources are released between reloads.
651
+ // Note: dispose must NOT call process.exit().
652
+ try {
653
+ const hot = (import.meta as any)?.hot
654
+ if (hot && typeof hot.dispose === 'function') {
655
+ hot.dispose(() => {
656
+ void cleanup()
657
+ })
658
+ }
659
+ } catch {}
644
660
 
645
661
  // Prefer Bun if available, then Node.js; otherwise instruct the user to serve manually
646
662
  if (typeof process !== 'undefined' && process.versions?.bun) {
@@ -774,6 +790,8 @@ function startDrizzleStudio(port: number): boolean {
774
790
  */
775
791
  function stopDrizzleStudio(): void {
776
792
  if (drizzleStudioProcess) {
793
+ // Remove all event listeners to prevent memory leaks
794
+ drizzleStudioProcess.removeAllListeners()
777
795
  drizzleStudioProcess.kill()
778
796
  drizzleStudioProcess = null
779
797
  console.log('🛑 Drizzle Studio stopped')