@spfn/core 0.2.0-beta.17 → 0.2.0-beta.19

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.
@@ -34,6 +34,7 @@ declare const coreEnvSchema: {
34
34
  examples: string[];
35
35
  } & {
36
36
  type: "string";
37
+ validator: (value: string) => string;
37
38
  } & {
38
39
  key: "DATABASE_URL";
39
40
  };
@@ -45,6 +46,7 @@ declare const coreEnvSchema: {
45
46
  examples: string[];
46
47
  } & {
47
48
  type: "string";
49
+ validator: (value: string) => string;
48
50
  } & {
49
51
  key: "DATABASE_WRITE_URL";
50
52
  };
@@ -56,6 +58,7 @@ declare const coreEnvSchema: {
56
58
  examples: string[];
57
59
  } & {
58
60
  type: "string";
61
+ validator: (value: string) => string;
59
62
  } & {
60
63
  key: "DATABASE_READ_URL";
61
64
  };
@@ -226,6 +229,7 @@ declare const coreEnvSchema: {
226
229
  examples: string[];
227
230
  } & {
228
231
  type: "string";
232
+ validator: (value: string) => string;
229
233
  } & {
230
234
  key: "DRIZZLE_SCHEMA_PATH";
231
235
  };
@@ -236,6 +240,7 @@ declare const coreEnvSchema: {
236
240
  examples: string[];
237
241
  } & {
238
242
  type: "string";
243
+ validator: (value: string) => string;
239
244
  } & {
240
245
  key: "DRIZZLE_OUT_DIR";
241
246
  };
@@ -253,6 +258,7 @@ declare const coreEnvSchema: {
253
258
  examples: string[];
254
259
  } & {
255
260
  type: "string";
261
+ validator: (value: string) => string;
256
262
  } & {
257
263
  key: "CACHE_URL";
258
264
  };
@@ -264,6 +270,7 @@ declare const coreEnvSchema: {
264
270
  examples: string[];
265
271
  } & {
266
272
  type: "string";
273
+ validator: (value: string) => string;
267
274
  } & {
268
275
  key: "CACHE_WRITE_URL";
269
276
  };
@@ -275,6 +282,7 @@ declare const coreEnvSchema: {
275
282
  examples: string[];
276
283
  } & {
277
284
  type: "string";
285
+ validator: (value: string) => string;
278
286
  } & {
279
287
  key: "CACHE_READ_URL";
280
288
  };
@@ -284,6 +292,7 @@ declare const coreEnvSchema: {
284
292
  examples: string[];
285
293
  } & {
286
294
  type: "string";
295
+ validator: (value: string) => string;
287
296
  } & {
288
297
  key: "CACHE_SENTINEL_HOSTS";
289
298
  };
@@ -293,6 +302,7 @@ declare const coreEnvSchema: {
293
302
  examples: string[];
294
303
  } & {
295
304
  type: "string";
305
+ validator: (value: string) => string;
296
306
  } & {
297
307
  key: "CACHE_CLUSTER_NODES";
298
308
  };
@@ -302,6 +312,7 @@ declare const coreEnvSchema: {
302
312
  examples: string[];
303
313
  } & {
304
314
  type: "string";
315
+ validator: (value: string) => string;
305
316
  } & {
306
317
  key: "CACHE_MASTER_NAME";
307
318
  };
@@ -312,6 +323,7 @@ declare const coreEnvSchema: {
312
323
  examples: string[];
313
324
  } & {
314
325
  type: "string";
326
+ validator: (value: string) => string;
315
327
  } & {
316
328
  key: "CACHE_PASSWORD";
317
329
  };
@@ -342,6 +354,7 @@ declare const coreEnvSchema: {
342
354
  examples: string[];
343
355
  } & {
344
356
  type: "string";
357
+ validator: (value: string) => string;
345
358
  } & {
346
359
  key: "HOST";
347
360
  };
@@ -441,6 +454,7 @@ declare const registry: _spfn_core_env.EnvRegistry<{
441
454
  examples: string[];
442
455
  } & {
443
456
  type: "string";
457
+ validator: (value: string) => string;
444
458
  } & {
445
459
  key: "DATABASE_URL";
446
460
  };
@@ -452,6 +466,7 @@ declare const registry: _spfn_core_env.EnvRegistry<{
452
466
  examples: string[];
453
467
  } & {
454
468
  type: "string";
469
+ validator: (value: string) => string;
455
470
  } & {
456
471
  key: "DATABASE_WRITE_URL";
457
472
  };
@@ -463,6 +478,7 @@ declare const registry: _spfn_core_env.EnvRegistry<{
463
478
  examples: string[];
464
479
  } & {
465
480
  type: "string";
481
+ validator: (value: string) => string;
466
482
  } & {
467
483
  key: "DATABASE_READ_URL";
468
484
  };
@@ -633,6 +649,7 @@ declare const registry: _spfn_core_env.EnvRegistry<{
633
649
  examples: string[];
634
650
  } & {
635
651
  type: "string";
652
+ validator: (value: string) => string;
636
653
  } & {
637
654
  key: "DRIZZLE_SCHEMA_PATH";
638
655
  };
@@ -643,6 +660,7 @@ declare const registry: _spfn_core_env.EnvRegistry<{
643
660
  examples: string[];
644
661
  } & {
645
662
  type: "string";
663
+ validator: (value: string) => string;
646
664
  } & {
647
665
  key: "DRIZZLE_OUT_DIR";
648
666
  };
@@ -660,6 +678,7 @@ declare const registry: _spfn_core_env.EnvRegistry<{
660
678
  examples: string[];
661
679
  } & {
662
680
  type: "string";
681
+ validator: (value: string) => string;
663
682
  } & {
664
683
  key: "CACHE_URL";
665
684
  };
@@ -671,6 +690,7 @@ declare const registry: _spfn_core_env.EnvRegistry<{
671
690
  examples: string[];
672
691
  } & {
673
692
  type: "string";
693
+ validator: (value: string) => string;
674
694
  } & {
675
695
  key: "CACHE_WRITE_URL";
676
696
  };
@@ -682,6 +702,7 @@ declare const registry: _spfn_core_env.EnvRegistry<{
682
702
  examples: string[];
683
703
  } & {
684
704
  type: "string";
705
+ validator: (value: string) => string;
685
706
  } & {
686
707
  key: "CACHE_READ_URL";
687
708
  };
@@ -691,6 +712,7 @@ declare const registry: _spfn_core_env.EnvRegistry<{
691
712
  examples: string[];
692
713
  } & {
693
714
  type: "string";
715
+ validator: (value: string) => string;
694
716
  } & {
695
717
  key: "CACHE_SENTINEL_HOSTS";
696
718
  };
@@ -700,6 +722,7 @@ declare const registry: _spfn_core_env.EnvRegistry<{
700
722
  examples: string[];
701
723
  } & {
702
724
  type: "string";
725
+ validator: (value: string) => string;
703
726
  } & {
704
727
  key: "CACHE_CLUSTER_NODES";
705
728
  };
@@ -709,6 +732,7 @@ declare const registry: _spfn_core_env.EnvRegistry<{
709
732
  examples: string[];
710
733
  } & {
711
734
  type: "string";
735
+ validator: (value: string) => string;
712
736
  } & {
713
737
  key: "CACHE_MASTER_NAME";
714
738
  };
@@ -719,6 +743,7 @@ declare const registry: _spfn_core_env.EnvRegistry<{
719
743
  examples: string[];
720
744
  } & {
721
745
  type: "string";
746
+ validator: (value: string) => string;
722
747
  } & {
723
748
  key: "CACHE_PASSWORD";
724
749
  };
@@ -749,6 +774,7 @@ declare const registry: _spfn_core_env.EnvRegistry<{
749
774
  examples: string[];
750
775
  } & {
751
776
  type: "string";
777
+ validator: (value: string) => string;
752
778
  } & {
753
779
  key: "HOST";
754
780
  };
@@ -841,6 +867,7 @@ declare const env: _spfn_core_env.InferEnvType<{
841
867
  examples: string[];
842
868
  } & {
843
869
  type: "string";
870
+ validator: (value: string) => string;
844
871
  } & {
845
872
  key: "DATABASE_URL";
846
873
  };
@@ -852,6 +879,7 @@ declare const env: _spfn_core_env.InferEnvType<{
852
879
  examples: string[];
853
880
  } & {
854
881
  type: "string";
882
+ validator: (value: string) => string;
855
883
  } & {
856
884
  key: "DATABASE_WRITE_URL";
857
885
  };
@@ -863,6 +891,7 @@ declare const env: _spfn_core_env.InferEnvType<{
863
891
  examples: string[];
864
892
  } & {
865
893
  type: "string";
894
+ validator: (value: string) => string;
866
895
  } & {
867
896
  key: "DATABASE_READ_URL";
868
897
  };
@@ -1033,6 +1062,7 @@ declare const env: _spfn_core_env.InferEnvType<{
1033
1062
  examples: string[];
1034
1063
  } & {
1035
1064
  type: "string";
1065
+ validator: (value: string) => string;
1036
1066
  } & {
1037
1067
  key: "DRIZZLE_SCHEMA_PATH";
1038
1068
  };
@@ -1043,6 +1073,7 @@ declare const env: _spfn_core_env.InferEnvType<{
1043
1073
  examples: string[];
1044
1074
  } & {
1045
1075
  type: "string";
1076
+ validator: (value: string) => string;
1046
1077
  } & {
1047
1078
  key: "DRIZZLE_OUT_DIR";
1048
1079
  };
@@ -1060,6 +1091,7 @@ declare const env: _spfn_core_env.InferEnvType<{
1060
1091
  examples: string[];
1061
1092
  } & {
1062
1093
  type: "string";
1094
+ validator: (value: string) => string;
1063
1095
  } & {
1064
1096
  key: "CACHE_URL";
1065
1097
  };
@@ -1071,6 +1103,7 @@ declare const env: _spfn_core_env.InferEnvType<{
1071
1103
  examples: string[];
1072
1104
  } & {
1073
1105
  type: "string";
1106
+ validator: (value: string) => string;
1074
1107
  } & {
1075
1108
  key: "CACHE_WRITE_URL";
1076
1109
  };
@@ -1082,6 +1115,7 @@ declare const env: _spfn_core_env.InferEnvType<{
1082
1115
  examples: string[];
1083
1116
  } & {
1084
1117
  type: "string";
1118
+ validator: (value: string) => string;
1085
1119
  } & {
1086
1120
  key: "CACHE_READ_URL";
1087
1121
  };
@@ -1091,6 +1125,7 @@ declare const env: _spfn_core_env.InferEnvType<{
1091
1125
  examples: string[];
1092
1126
  } & {
1093
1127
  type: "string";
1128
+ validator: (value: string) => string;
1094
1129
  } & {
1095
1130
  key: "CACHE_SENTINEL_HOSTS";
1096
1131
  };
@@ -1100,6 +1135,7 @@ declare const env: _spfn_core_env.InferEnvType<{
1100
1135
  examples: string[];
1101
1136
  } & {
1102
1137
  type: "string";
1138
+ validator: (value: string) => string;
1103
1139
  } & {
1104
1140
  key: "CACHE_CLUSTER_NODES";
1105
1141
  };
@@ -1109,6 +1145,7 @@ declare const env: _spfn_core_env.InferEnvType<{
1109
1145
  examples: string[];
1110
1146
  } & {
1111
1147
  type: "string";
1148
+ validator: (value: string) => string;
1112
1149
  } & {
1113
1150
  key: "CACHE_MASTER_NAME";
1114
1151
  };
@@ -1119,6 +1156,7 @@ declare const env: _spfn_core_env.InferEnvType<{
1119
1156
  examples: string[];
1120
1157
  } & {
1121
1158
  type: "string";
1159
+ validator: (value: string) => string;
1122
1160
  } & {
1123
1161
  key: "CACHE_PASSWORD";
1124
1162
  };
@@ -1149,6 +1187,7 @@ declare const env: _spfn_core_env.InferEnvType<{
1149
1187
  examples: string[];
1150
1188
  } & {
1151
1189
  type: "string";
1190
+ validator: (value: string) => string;
1152
1191
  } & {
1153
1192
  key: "HOST";
1154
1193
  };
package/dist/db/index.js CHANGED
@@ -503,6 +503,8 @@ var setMonitoringConfig = (config) => {
503
503
  globalThis.__SPFN_DB_MONITORING__ = config;
504
504
  };
505
505
  var dbLogger3 = logger.child("@spfn/core:database");
506
+ var CLIENT_CLOSE_TIMEOUT = 5;
507
+ var isReconnecting = false;
506
508
  async function testDatabaseConnection(db) {
507
509
  await db.execute("SELECT 1");
508
510
  }
@@ -514,8 +516,13 @@ async function performHealthCheck(getDatabase2) {
514
516
  await testDatabaseConnection(read);
515
517
  }
516
518
  }
517
- async function reconnectAndRestore(options, closeDatabase2) {
518
- await closeDatabase2();
519
+ async function closeClient(client) {
520
+ try {
521
+ await client.end({ timeout: CLIENT_CLOSE_TIMEOUT });
522
+ } catch {
523
+ }
524
+ }
525
+ async function reconnectAndRestore(options) {
519
526
  const result = await createDatabaseFromEnv(options);
520
527
  if (!result.write) {
521
528
  return false;
@@ -524,15 +531,23 @@ async function reconnectAndRestore(options, closeDatabase2) {
524
531
  if (result.read && result.read !== result.write) {
525
532
  await testDatabaseConnection(result.read);
526
533
  }
534
+ const oldWriteClient = getWriteClient();
535
+ const oldReadClient = getReadClient();
527
536
  setWriteInstance(result.write);
528
537
  setReadInstance(result.read);
529
538
  setWriteClient(result.writeClient);
530
539
  setReadClient(result.readClient);
531
540
  const monConfig = buildMonitoringConfig(options?.monitoring);
532
541
  setMonitoringConfig(monConfig);
542
+ if (oldWriteClient) {
543
+ closeClient(oldWriteClient);
544
+ }
545
+ if (oldReadClient && oldReadClient !== oldWriteClient) {
546
+ closeClient(oldReadClient);
547
+ }
533
548
  return true;
534
549
  }
535
- function startHealthCheck(config, options, getDatabase2, closeDatabase2) {
550
+ function startHealthCheck(config, options, getDatabase2) {
536
551
  const healthCheck = getHealthCheckInterval();
537
552
  if (healthCheck) {
538
553
  dbLogger3.debug("Health check already running");
@@ -543,47 +558,56 @@ function startHealthCheck(config, options, getDatabase2, closeDatabase2) {
543
558
  reconnect: config.reconnect
544
559
  });
545
560
  const interval = setInterval(async () => {
561
+ if (isReconnecting) {
562
+ dbLogger3.debug("Health check skipped: reconnection in progress");
563
+ return;
564
+ }
546
565
  try {
547
566
  await performHealthCheck(getDatabase2);
548
567
  } catch (error) {
549
568
  const message = error instanceof Error ? error.message : "Unknown error";
550
569
  dbLogger3.error("Database health check failed", { error: message });
551
570
  if (config.reconnect) {
552
- await attemptReconnection(config, options, closeDatabase2);
571
+ await attemptReconnection(config, options);
553
572
  }
554
573
  }
555
574
  }, config.interval);
556
575
  setHealthCheckInterval(interval);
557
576
  }
558
- async function attemptReconnection(config, options, closeDatabase2) {
577
+ async function attemptReconnection(config, options) {
578
+ isReconnecting = true;
559
579
  dbLogger3.warn("Attempting database reconnection", {
560
580
  maxRetries: config.maxRetries,
561
581
  retryInterval: `${config.retryInterval}ms`
562
582
  });
563
- for (let attempt = 1; attempt <= config.maxRetries; attempt++) {
564
- try {
565
- dbLogger3.debug(`Reconnection attempt ${attempt}/${config.maxRetries}`);
566
- if (attempt > 1) {
567
- await new Promise((resolve) => setTimeout(resolve, config.retryInterval));
583
+ try {
584
+ for (let attempt = 1; attempt <= config.maxRetries; attempt++) {
585
+ try {
586
+ dbLogger3.debug(`Reconnection attempt ${attempt}/${config.maxRetries}`);
587
+ if (attempt > 1) {
588
+ await new Promise((resolve) => setTimeout(resolve, config.retryInterval));
589
+ }
590
+ const success = await reconnectAndRestore(options);
591
+ if (success) {
592
+ dbLogger3.info("Database reconnection successful", { attempt });
593
+ return;
594
+ } else {
595
+ dbLogger3.error(`Reconnection attempt ${attempt} failed: No write database instance created`);
596
+ }
597
+ } catch (error) {
598
+ const message = error instanceof Error ? error.message : "Unknown error";
599
+ dbLogger3.error(`Reconnection attempt ${attempt} failed`, {
600
+ error: message,
601
+ attempt,
602
+ maxRetries: config.maxRetries
603
+ });
568
604
  }
569
- const success = await reconnectAndRestore(options, closeDatabase2);
570
- if (success) {
571
- dbLogger3.info("Database reconnection successful", { attempt });
572
- return;
573
- } else {
574
- dbLogger3.error(`Reconnection attempt ${attempt} failed: No write database instance created`);
605
+ if (attempt === config.maxRetries) {
606
+ dbLogger3.error("Max reconnection attempts reached, will retry on next health check");
575
607
  }
576
- } catch (error) {
577
- const message = error instanceof Error ? error.message : "Unknown error";
578
- dbLogger3.error(`Reconnection attempt ${attempt} failed`, {
579
- error: message,
580
- attempt,
581
- maxRetries: config.maxRetries
582
- });
583
- }
584
- if (attempt === config.maxRetries) {
585
- dbLogger3.error("Max reconnection attempts reached, giving up");
586
608
  }
609
+ } finally {
610
+ isReconnecting = false;
587
611
  }
588
612
  }
589
613
  function stopHealthCheck() {
@@ -593,6 +617,7 @@ function stopHealthCheck() {
593
617
  setHealthCheckInterval(void 0);
594
618
  dbLogger3.info("Database health check stopped");
595
619
  }
620
+ isReconnecting = false;
596
621
  }
597
622
 
598
623
  // src/db/manager/manager.ts
@@ -742,7 +767,7 @@ async function initDatabase(options) {
742
767
  );
743
768
  const healthCheckConfig = buildHealthCheckConfig(options?.healthCheck);
744
769
  if (healthCheckConfig.enabled) {
745
- startHealthCheck(healthCheckConfig, options, getDatabase, closeDatabase);
770
+ startHealthCheck(healthCheckConfig, options, getDatabase);
746
771
  }
747
772
  const monConfig = buildMonitoringConfig(options?.monitoring);
748
773
  setMonitoringConfig(monConfig);