drizzle-multitenant 1.0.8 → 1.0.9

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.
@@ -1,7 +1,7 @@
1
1
  import { Request, Response, NextFunction, RequestHandler } from 'express';
2
- import { T as TenantManager } from '../types-DKVaTaIb.js';
3
- import { T as TenantContextData, a as TenantContext } from '../context-DBerWr50.js';
4
- export { c as createTenantContext } from '../context-DBerWr50.js';
2
+ import { T as TenantManager } from '../types-B5eSRLFW.js';
3
+ import { T as TenantContextData, a as TenantContext } from '../context-DoHx79MS.js';
4
+ export { c as createTenantContext } from '../context-DoHx79MS.js';
5
5
  import 'pg';
6
6
  import 'drizzle-orm/node-postgres';
7
7
 
@@ -1,7 +1,7 @@
1
1
  import { FastifyRequest, FastifyReply, FastifyPluginAsync } from 'fastify';
2
- import { T as TenantManager } from '../types-DKVaTaIb.js';
3
- import { T as TenantContextData, a as TenantContext } from '../context-DBerWr50.js';
4
- export { c as createTenantContext } from '../context-DBerWr50.js';
2
+ import { T as TenantManager } from '../types-B5eSRLFW.js';
3
+ import { T as TenantContextData, a as TenantContext } from '../context-DoHx79MS.js';
4
+ export { c as createTenantContext } from '../context-DoHx79MS.js';
5
5
  import 'pg';
6
6
  import 'drizzle-orm/node-postgres';
7
7
 
@@ -1,7 +1,7 @@
1
1
  import * as _nestjs_common from '@nestjs/common';
2
2
  import { ModuleMetadata, Type, InjectionToken, DynamicModule, CanActivate, ExecutionContext, NestInterceptor, CallHandler, Provider } from '@nestjs/common';
3
3
  import { Request } from 'express';
4
- import { C as Config, a as TenantDb, T as TenantManager, S as SharedDb } from '../../types-DKVaTaIb.js';
4
+ import { C as Config, a as TenantDb, T as TenantManager, S as SharedDb } from '../../types-B5eSRLFW.js';
5
5
  import { Reflector } from '@nestjs/core';
6
6
  import { Observable } from 'rxjs';
7
7
  import 'pg';
@@ -9225,14 +9225,265 @@ var DEFAULT_CONFIG = {
9225
9225
  max: 10,
9226
9226
  idleTimeoutMillis: 3e4,
9227
9227
  connectionTimeoutMillis: 5e3
9228
+ },
9229
+ retry: {
9230
+ maxAttempts: 3,
9231
+ initialDelayMs: 100,
9232
+ maxDelayMs: 5e3,
9233
+ backoffMultiplier: 2,
9234
+ jitter: true
9228
9235
  }
9229
9236
  };
9230
9237
 
9238
+ // src/debug.ts
9239
+ var PREFIX = "[drizzle-multitenant]";
9240
+ var DEFAULT_SLOW_QUERY_THRESHOLD = 1e3;
9241
+ var DebugLogger = class {
9242
+ enabled;
9243
+ logQueries;
9244
+ logPoolEvents;
9245
+ slowQueryThreshold;
9246
+ logger;
9247
+ constructor(config) {
9248
+ this.enabled = config?.enabled ?? false;
9249
+ this.logQueries = config?.logQueries ?? true;
9250
+ this.logPoolEvents = config?.logPoolEvents ?? true;
9251
+ this.slowQueryThreshold = config?.slowQueryThreshold ?? DEFAULT_SLOW_QUERY_THRESHOLD;
9252
+ this.logger = config?.logger ?? this.defaultLogger;
9253
+ }
9254
+ /**
9255
+ * Check if debug mode is enabled
9256
+ */
9257
+ isEnabled() {
9258
+ return this.enabled;
9259
+ }
9260
+ /**
9261
+ * Log a query execution
9262
+ */
9263
+ logQuery(tenantId, query, durationMs) {
9264
+ if (!this.enabled || !this.logQueries) return;
9265
+ const isSlowQuery = durationMs >= this.slowQueryThreshold;
9266
+ const type = isSlowQuery ? "slow_query" : "query";
9267
+ const context = {
9268
+ type,
9269
+ tenantId,
9270
+ query: this.truncateQuery(query),
9271
+ durationMs
9272
+ };
9273
+ if (isSlowQuery) {
9274
+ this.logger(
9275
+ `${PREFIX} tenant=${tenantId} SLOW_QUERY duration=${durationMs}ms query="${this.truncateQuery(query)}"`,
9276
+ context
9277
+ );
9278
+ } else {
9279
+ this.logger(
9280
+ `${PREFIX} tenant=${tenantId} query="${this.truncateQuery(query)}" duration=${durationMs}ms`,
9281
+ context
9282
+ );
9283
+ }
9284
+ }
9285
+ /**
9286
+ * Log pool creation
9287
+ */
9288
+ logPoolCreated(tenantId, schemaName) {
9289
+ if (!this.enabled || !this.logPoolEvents) return;
9290
+ const context = {
9291
+ type: "pool_created",
9292
+ tenantId,
9293
+ schemaName
9294
+ };
9295
+ this.logger(
9296
+ `${PREFIX} tenant=${tenantId} POOL_CREATED schema=${schemaName}`,
9297
+ context
9298
+ );
9299
+ }
9300
+ /**
9301
+ * Log pool eviction
9302
+ */
9303
+ logPoolEvicted(tenantId, schemaName, reason) {
9304
+ if (!this.enabled || !this.logPoolEvents) return;
9305
+ const context = {
9306
+ type: "pool_evicted",
9307
+ tenantId,
9308
+ schemaName,
9309
+ metadata: reason ? { reason } : void 0
9310
+ };
9311
+ const reasonStr = reason ? ` reason=${reason}` : "";
9312
+ this.logger(
9313
+ `${PREFIX} tenant=${tenantId} POOL_EVICTED schema=${schemaName}${reasonStr}`,
9314
+ context
9315
+ );
9316
+ }
9317
+ /**
9318
+ * Log pool error
9319
+ */
9320
+ logPoolError(tenantId, error) {
9321
+ if (!this.enabled || !this.logPoolEvents) return;
9322
+ const context = {
9323
+ type: "pool_error",
9324
+ tenantId,
9325
+ error: error.message
9326
+ };
9327
+ this.logger(
9328
+ `${PREFIX} tenant=${tenantId} POOL_ERROR error="${error.message}"`,
9329
+ context
9330
+ );
9331
+ }
9332
+ /**
9333
+ * Log warmup event
9334
+ */
9335
+ logWarmup(tenantId, success, durationMs, alreadyWarm) {
9336
+ if (!this.enabled || !this.logPoolEvents) return;
9337
+ const context = {
9338
+ type: "warmup",
9339
+ tenantId,
9340
+ durationMs,
9341
+ metadata: { success, alreadyWarm }
9342
+ };
9343
+ const status = alreadyWarm ? "already_warm" : success ? "success" : "failed";
9344
+ this.logger(
9345
+ `${PREFIX} tenant=${tenantId} WARMUP status=${status} duration=${durationMs}ms`,
9346
+ context
9347
+ );
9348
+ }
9349
+ /**
9350
+ * Log connection retry event
9351
+ */
9352
+ logConnectionRetry(identifier, attempt, maxAttempts, error, delayMs) {
9353
+ if (!this.enabled || !this.logPoolEvents) return;
9354
+ const context = {
9355
+ type: "connection_retry",
9356
+ tenantId: identifier,
9357
+ error: error.message,
9358
+ metadata: { attempt, maxAttempts, delayMs }
9359
+ };
9360
+ this.logger(
9361
+ `${PREFIX} tenant=${identifier} CONNECTION_RETRY attempt=${attempt}/${maxAttempts} delay=${delayMs}ms error="${error.message}"`,
9362
+ context
9363
+ );
9364
+ }
9365
+ /**
9366
+ * Log connection success after retries
9367
+ */
9368
+ logConnectionSuccess(identifier, attempts, totalTimeMs) {
9369
+ if (!this.enabled || !this.logPoolEvents) return;
9370
+ const context = {
9371
+ type: "pool_created",
9372
+ tenantId: identifier,
9373
+ durationMs: totalTimeMs,
9374
+ metadata: { attempts }
9375
+ };
9376
+ if (attempts > 1) {
9377
+ this.logger(
9378
+ `${PREFIX} tenant=${identifier} CONNECTION_SUCCESS attempts=${attempts} totalTime=${totalTimeMs}ms`,
9379
+ context
9380
+ );
9381
+ }
9382
+ }
9383
+ /**
9384
+ * Log a custom debug message
9385
+ */
9386
+ log(message, context) {
9387
+ if (!this.enabled) return;
9388
+ this.logger(`${PREFIX} ${message}`, context);
9389
+ }
9390
+ /**
9391
+ * Default logger implementation using console
9392
+ */
9393
+ defaultLogger(message, _context) {
9394
+ console.log(message);
9395
+ }
9396
+ /**
9397
+ * Truncate long queries for readability
9398
+ */
9399
+ truncateQuery(query, maxLength = 100) {
9400
+ const normalized = query.replace(/\s+/g, " ").trim();
9401
+ if (normalized.length <= maxLength) {
9402
+ return normalized;
9403
+ }
9404
+ return normalized.substring(0, maxLength - 3) + "...";
9405
+ }
9406
+ };
9407
+ function createDebugLogger(config) {
9408
+ return new DebugLogger(config);
9409
+ }
9410
+
9411
+ // src/retry.ts
9412
+ function isRetryableError(error) {
9413
+ const message = error.message.toLowerCase();
9414
+ if (message.includes("econnrefused") || message.includes("econnreset") || message.includes("etimedout") || message.includes("enotfound") || message.includes("connection refused") || message.includes("connection reset") || message.includes("connection terminated") || message.includes("connection timed out") || message.includes("timeout expired") || message.includes("socket hang up")) {
9415
+ return true;
9416
+ }
9417
+ if (message.includes("too many connections") || message.includes("sorry, too many clients") || message.includes("the database system is starting up") || message.includes("the database system is shutting down") || message.includes("server closed the connection unexpectedly") || message.includes("could not connect to server")) {
9418
+ return true;
9419
+ }
9420
+ if (message.includes("ssl connection") || message.includes("ssl handshake")) {
9421
+ return true;
9422
+ }
9423
+ return false;
9424
+ }
9425
+ function calculateDelay(attempt, config) {
9426
+ const exponentialDelay = config.initialDelayMs * Math.pow(config.backoffMultiplier, attempt);
9427
+ const cappedDelay = Math.min(exponentialDelay, config.maxDelayMs);
9428
+ if (config.jitter) {
9429
+ const jitterFactor = 1 + Math.random() * 0.25;
9430
+ return Math.floor(cappedDelay * jitterFactor);
9431
+ }
9432
+ return Math.floor(cappedDelay);
9433
+ }
9434
+ function sleep(ms) {
9435
+ return new Promise((resolve) => setTimeout(resolve, ms));
9436
+ }
9437
+ async function withRetry(operation, config) {
9438
+ const retryConfig = {
9439
+ maxAttempts: config?.maxAttempts ?? DEFAULT_CONFIG.retry.maxAttempts,
9440
+ initialDelayMs: config?.initialDelayMs ?? DEFAULT_CONFIG.retry.initialDelayMs,
9441
+ maxDelayMs: config?.maxDelayMs ?? DEFAULT_CONFIG.retry.maxDelayMs,
9442
+ backoffMultiplier: config?.backoffMultiplier ?? DEFAULT_CONFIG.retry.backoffMultiplier,
9443
+ jitter: config?.jitter ?? DEFAULT_CONFIG.retry.jitter,
9444
+ isRetryable: config?.isRetryable ?? isRetryableError,
9445
+ onRetry: config?.onRetry
9446
+ };
9447
+ const startTime = Date.now();
9448
+ let lastError = null;
9449
+ for (let attempt = 0; attempt < retryConfig.maxAttempts; attempt++) {
9450
+ try {
9451
+ const result = await operation();
9452
+ return {
9453
+ result,
9454
+ attempts: attempt + 1,
9455
+ totalTimeMs: Date.now() - startTime
9456
+ };
9457
+ } catch (error) {
9458
+ lastError = error;
9459
+ const isLastAttempt = attempt >= retryConfig.maxAttempts - 1;
9460
+ if (isLastAttempt || !retryConfig.isRetryable(lastError)) {
9461
+ throw lastError;
9462
+ }
9463
+ const delay = calculateDelay(attempt, retryConfig);
9464
+ retryConfig.onRetry?.(attempt + 1, lastError, delay);
9465
+ await sleep(delay);
9466
+ }
9467
+ }
9468
+ throw lastError ?? new Error("Retry failed with no error");
9469
+ }
9470
+
9231
9471
  // src/pool.ts
9232
9472
  var PoolManager = class {
9233
9473
  constructor(config) {
9234
9474
  this.config = config;
9235
9475
  const maxPools = config.isolation.maxPools ?? DEFAULT_CONFIG.maxPools;
9476
+ this.debugLogger = createDebugLogger(config.debug);
9477
+ const userRetry = config.connection.retry ?? {};
9478
+ this.retryConfig = {
9479
+ maxAttempts: userRetry.maxAttempts ?? DEFAULT_CONFIG.retry.maxAttempts,
9480
+ initialDelayMs: userRetry.initialDelayMs ?? DEFAULT_CONFIG.retry.initialDelayMs,
9481
+ maxDelayMs: userRetry.maxDelayMs ?? DEFAULT_CONFIG.retry.maxDelayMs,
9482
+ backoffMultiplier: userRetry.backoffMultiplier ?? DEFAULT_CONFIG.retry.backoffMultiplier,
9483
+ jitter: userRetry.jitter ?? DEFAULT_CONFIG.retry.jitter,
9484
+ isRetryable: userRetry.isRetryable ?? isRetryableError,
9485
+ onRetry: userRetry.onRetry
9486
+ };
9236
9487
  this.pools = new LRUCache({
9237
9488
  max: maxPools,
9238
9489
  dispose: (entry, key) => {
@@ -9243,10 +9494,14 @@ var PoolManager = class {
9243
9494
  }
9244
9495
  pools;
9245
9496
  tenantIdBySchema = /* @__PURE__ */ new Map();
9497
+ pendingConnections = /* @__PURE__ */ new Map();
9246
9498
  sharedPool = null;
9247
9499
  sharedDb = null;
9500
+ sharedDbPending = null;
9248
9501
  cleanupInterval = null;
9249
9502
  disposed = false;
9503
+ debugLogger;
9504
+ retryConfig;
9250
9505
  /**
9251
9506
  * Get or create a database connection for a tenant
9252
9507
  */
@@ -9258,11 +9513,85 @@ var PoolManager = class {
9258
9513
  entry = this.createPoolEntry(tenantId, schemaName);
9259
9514
  this.pools.set(schemaName, entry);
9260
9515
  this.tenantIdBySchema.set(schemaName, tenantId);
9516
+ this.debugLogger.logPoolCreated(tenantId, schemaName);
9261
9517
  void this.config.hooks?.onPoolCreated?.(tenantId);
9262
9518
  }
9263
9519
  entry.lastAccess = Date.now();
9264
9520
  return entry.db;
9265
9521
  }
9522
+ /**
9523
+ * Get or create a database connection for a tenant with retry and validation
9524
+ *
9525
+ * This async version validates the connection by executing a ping query
9526
+ * and retries on transient failures with exponential backoff.
9527
+ *
9528
+ * @example
9529
+ * ```typescript
9530
+ * // Get tenant database with automatic retry
9531
+ * const db = await manager.getDbAsync('tenant-123');
9532
+ *
9533
+ * // Queries will use the validated connection
9534
+ * const users = await db.select().from(users);
9535
+ * ```
9536
+ */
9537
+ async getDbAsync(tenantId) {
9538
+ this.ensureNotDisposed();
9539
+ const schemaName = this.config.isolation.schemaNameTemplate(tenantId);
9540
+ let entry = this.pools.get(schemaName);
9541
+ if (entry) {
9542
+ entry.lastAccess = Date.now();
9543
+ return entry.db;
9544
+ }
9545
+ const pending = this.pendingConnections.get(schemaName);
9546
+ if (pending) {
9547
+ entry = await pending;
9548
+ entry.lastAccess = Date.now();
9549
+ return entry.db;
9550
+ }
9551
+ const connectionPromise = this.connectWithRetry(tenantId, schemaName);
9552
+ this.pendingConnections.set(schemaName, connectionPromise);
9553
+ try {
9554
+ entry = await connectionPromise;
9555
+ this.pools.set(schemaName, entry);
9556
+ this.tenantIdBySchema.set(schemaName, tenantId);
9557
+ this.debugLogger.logPoolCreated(tenantId, schemaName);
9558
+ void this.config.hooks?.onPoolCreated?.(tenantId);
9559
+ entry.lastAccess = Date.now();
9560
+ return entry.db;
9561
+ } finally {
9562
+ this.pendingConnections.delete(schemaName);
9563
+ }
9564
+ }
9565
+ /**
9566
+ * Connect to a tenant database with retry logic
9567
+ */
9568
+ async connectWithRetry(tenantId, schemaName) {
9569
+ const maxAttempts = this.retryConfig.maxAttempts;
9570
+ const result = await withRetry(
9571
+ async () => {
9572
+ const entry = this.createPoolEntry(tenantId, schemaName);
9573
+ try {
9574
+ await entry.pool.query("SELECT 1");
9575
+ return entry;
9576
+ } catch (error) {
9577
+ try {
9578
+ await entry.pool.end();
9579
+ } catch {
9580
+ }
9581
+ throw error;
9582
+ }
9583
+ },
9584
+ {
9585
+ ...this.retryConfig,
9586
+ onRetry: (attempt, error, delayMs) => {
9587
+ this.debugLogger.logConnectionRetry(tenantId, attempt, maxAttempts, error, delayMs);
9588
+ this.retryConfig.onRetry?.(attempt, error, delayMs);
9589
+ }
9590
+ }
9591
+ );
9592
+ this.debugLogger.logConnectionSuccess(tenantId, result.attempts, result.totalTimeMs);
9593
+ return result.result;
9594
+ }
9266
9595
  /**
9267
9596
  * Get or create the shared database connection
9268
9597
  */
@@ -9283,6 +9612,78 @@ var PoolManager = class {
9283
9612
  }
9284
9613
  return this.sharedDb;
9285
9614
  }
9615
+ /**
9616
+ * Get or create the shared database connection with retry and validation
9617
+ *
9618
+ * This async version validates the connection by executing a ping query
9619
+ * and retries on transient failures with exponential backoff.
9620
+ *
9621
+ * @example
9622
+ * ```typescript
9623
+ * // Get shared database with automatic retry
9624
+ * const sharedDb = await manager.getSharedDbAsync();
9625
+ *
9626
+ * // Queries will use the validated connection
9627
+ * const plans = await sharedDb.select().from(plans);
9628
+ * ```
9629
+ */
9630
+ async getSharedDbAsync() {
9631
+ this.ensureNotDisposed();
9632
+ if (this.sharedDb) {
9633
+ return this.sharedDb;
9634
+ }
9635
+ if (this.sharedDbPending) {
9636
+ return this.sharedDbPending;
9637
+ }
9638
+ this.sharedDbPending = this.connectSharedWithRetry();
9639
+ try {
9640
+ const db = await this.sharedDbPending;
9641
+ return db;
9642
+ } finally {
9643
+ this.sharedDbPending = null;
9644
+ }
9645
+ }
9646
+ /**
9647
+ * Connect to shared database with retry logic
9648
+ */
9649
+ async connectSharedWithRetry() {
9650
+ const maxAttempts = this.retryConfig.maxAttempts;
9651
+ const result = await withRetry(
9652
+ async () => {
9653
+ const pool = new Pool({
9654
+ connectionString: this.config.connection.url,
9655
+ ...DEFAULT_CONFIG.poolConfig,
9656
+ ...this.config.connection.poolConfig
9657
+ });
9658
+ try {
9659
+ await pool.query("SELECT 1");
9660
+ pool.on("error", (err) => {
9661
+ void this.config.hooks?.onError?.("shared", err);
9662
+ });
9663
+ this.sharedPool = pool;
9664
+ this.sharedDb = drizzle(pool, {
9665
+ schema: this.config.schemas.shared
9666
+ });
9667
+ return this.sharedDb;
9668
+ } catch (error) {
9669
+ try {
9670
+ await pool.end();
9671
+ } catch {
9672
+ }
9673
+ throw error;
9674
+ }
9675
+ },
9676
+ {
9677
+ ...this.retryConfig,
9678
+ onRetry: (attempt, error, delayMs) => {
9679
+ this.debugLogger.logConnectionRetry("shared", attempt, maxAttempts, error, delayMs);
9680
+ this.retryConfig.onRetry?.(attempt, error, delayMs);
9681
+ }
9682
+ }
9683
+ );
9684
+ this.debugLogger.logConnectionSuccess("shared", result.attempts, result.totalTimeMs);
9685
+ return result.result;
9686
+ }
9286
9687
  /**
9287
9688
  * Get schema name for a tenant
9288
9689
  */
@@ -9308,13 +9709,77 @@ var PoolManager = class {
9308
9709
  getActiveTenantIds() {
9309
9710
  return Array.from(this.tenantIdBySchema.values());
9310
9711
  }
9712
+ /**
9713
+ * Get the retry configuration
9714
+ */
9715
+ getRetryConfig() {
9716
+ return { ...this.retryConfig };
9717
+ }
9718
+ /**
9719
+ * Pre-warm pools for specified tenants to reduce cold start latency
9720
+ *
9721
+ * Uses automatic retry with exponential backoff for connection failures.
9722
+ */
9723
+ async warmup(tenantIds, options = {}) {
9724
+ this.ensureNotDisposed();
9725
+ const startTime = Date.now();
9726
+ const { concurrency = 10, ping = true, onProgress } = options;
9727
+ const results = [];
9728
+ for (let i = 0; i < tenantIds.length; i += concurrency) {
9729
+ const batch = tenantIds.slice(i, i + concurrency);
9730
+ const batchResults = await Promise.all(
9731
+ batch.map(async (tenantId) => {
9732
+ const tenantStart = Date.now();
9733
+ onProgress?.(tenantId, "starting");
9734
+ try {
9735
+ const alreadyWarm = this.hasPool(tenantId);
9736
+ if (ping) {
9737
+ await this.getDbAsync(tenantId);
9738
+ } else {
9739
+ this.getDb(tenantId);
9740
+ }
9741
+ const durationMs = Date.now() - tenantStart;
9742
+ onProgress?.(tenantId, "completed");
9743
+ this.debugLogger.logWarmup(tenantId, true, durationMs, alreadyWarm);
9744
+ return {
9745
+ tenantId,
9746
+ success: true,
9747
+ alreadyWarm,
9748
+ durationMs
9749
+ };
9750
+ } catch (error) {
9751
+ const durationMs = Date.now() - tenantStart;
9752
+ onProgress?.(tenantId, "failed");
9753
+ this.debugLogger.logWarmup(tenantId, false, durationMs, false);
9754
+ return {
9755
+ tenantId,
9756
+ success: false,
9757
+ alreadyWarm: false,
9758
+ durationMs,
9759
+ error: error.message
9760
+ };
9761
+ }
9762
+ })
9763
+ );
9764
+ results.push(...batchResults);
9765
+ }
9766
+ return {
9767
+ total: results.length,
9768
+ succeeded: results.filter((r) => r.success).length,
9769
+ failed: results.filter((r) => !r.success).length,
9770
+ alreadyWarm: results.filter((r) => r.alreadyWarm).length,
9771
+ durationMs: Date.now() - startTime,
9772
+ details: results
9773
+ };
9774
+ }
9311
9775
  /**
9312
9776
  * Manually evict a tenant pool
9313
9777
  */
9314
- async evictPool(tenantId) {
9778
+ async evictPool(tenantId, reason = "manual") {
9315
9779
  const schemaName = this.config.isolation.schemaNameTemplate(tenantId);
9316
9780
  const entry = this.pools.get(schemaName);
9317
9781
  if (entry) {
9782
+ this.debugLogger.logPoolEvicted(tenantId, schemaName, reason);
9318
9783
  this.pools.delete(schemaName);
9319
9784
  this.tenantIdBySchema.delete(schemaName);
9320
9785
  await this.closePool(entry.pool, tenantId);
@@ -9373,8 +9838,9 @@ var PoolManager = class {
9373
9838
  options: `-c search_path=${schemaName},public`
9374
9839
  });
9375
9840
  pool.on("error", async (err) => {
9841
+ this.debugLogger.logPoolError(tenantId, err);
9376
9842
  void this.config.hooks?.onError?.(tenantId, err);
9377
- await this.evictPool(tenantId);
9843
+ await this.evictPool(tenantId, "error");
9378
9844
  });
9379
9845
  const db = drizzle(pool, {
9380
9846
  schema: this.config.schemas.tenant
@@ -9392,6 +9858,9 @@ var PoolManager = class {
9392
9858
  disposePoolEntry(entry, schemaName) {
9393
9859
  const tenantId = this.tenantIdBySchema.get(schemaName);
9394
9860
  this.tenantIdBySchema.delete(schemaName);
9861
+ if (tenantId) {
9862
+ this.debugLogger.logPoolEvicted(tenantId, schemaName, "lru_eviction");
9863
+ }
9395
9864
  void this.closePool(entry.pool, tenantId ?? schemaName).then(() => {
9396
9865
  if (tenantId) {
9397
9866
  void this.config.hooks?.onPoolEvicted?.(tenantId);
@@ -9422,7 +9891,7 @@ var PoolManager = class {
9422
9891
  for (const schemaName of toEvict) {
9423
9892
  const tenantId = this.tenantIdBySchema.get(schemaName);
9424
9893
  if (tenantId) {
9425
- await this.evictPool(tenantId);
9894
+ await this.evictPool(tenantId, "ttl_expired");
9426
9895
  }
9427
9896
  }
9428
9897
  }
@@ -9444,9 +9913,15 @@ function createTenantManager(config) {
9444
9913
  getDb(tenantId) {
9445
9914
  return poolManager.getDb(tenantId);
9446
9915
  },
9916
+ async getDbAsync(tenantId) {
9917
+ return poolManager.getDbAsync(tenantId);
9918
+ },
9447
9919
  getSharedDb() {
9448
9920
  return poolManager.getSharedDb();
9449
9921
  },
9922
+ async getSharedDbAsync() {
9923
+ return poolManager.getSharedDbAsync();
9924
+ },
9450
9925
  getSchemaName(tenantId) {
9451
9926
  return poolManager.getSchemaName(tenantId);
9452
9927
  },
@@ -9459,9 +9934,15 @@ function createTenantManager(config) {
9459
9934
  getActiveTenantIds() {
9460
9935
  return poolManager.getActiveTenantIds();
9461
9936
  },
9937
+ getRetryConfig() {
9938
+ return poolManager.getRetryConfig();
9939
+ },
9462
9940
  async evictPool(tenantId) {
9463
9941
  await poolManager.evictPool(tenantId);
9464
9942
  },
9943
+ async warmup(tenantIds, options) {
9944
+ return poolManager.warmup(tenantIds, options);
9945
+ },
9465
9946
  async dispose() {
9466
9947
  await poolManager.dispose();
9467
9948
  }