@dxos/async 0.7.5-labs.ea4b4c2 → 0.7.5-labs.f400bbc

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.
@@ -507,6 +507,98 @@ var latch = ({ count = 1, timeout } = {}) => {
507
507
  ];
508
508
  };
509
509
 
510
+ // packages/common/async/src/mutex.ts
511
+ import "@dxos/util";
512
+ import { warnAfterTimeout } from "@dxos/debug";
513
+ var Mutex = class {
514
+ constructor() {
515
+ this._queue = Promise.resolve();
516
+ this._queueLength = 0;
517
+ this._tag = null;
518
+ }
519
+ get tag() {
520
+ return this._tag;
521
+ }
522
+ isLocked() {
523
+ return this._queueLength > 0;
524
+ }
525
+ /**
526
+ * Acquires the lock.
527
+ * Caller is responsible for releasing the lock using the returned callback.
528
+ * NOTE: Using `executeSynchronized` is preferred over using `acquire` directly.
529
+ * @returns Release callback
530
+ */
531
+ async acquire(tag) {
532
+ const prev = this._queue;
533
+ let guard;
534
+ this._queueLength++;
535
+ this._queue = new Promise((resolve) => {
536
+ guard = new MutexGuard(() => {
537
+ this._queueLength--;
538
+ this._tag = null;
539
+ resolve();
540
+ });
541
+ });
542
+ await prev;
543
+ if (tag !== void 0) {
544
+ this._tag = tag;
545
+ }
546
+ return guard;
547
+ }
548
+ /**
549
+ * Waits for all previous executions to complete and then executes a given function.
550
+ * Only a single function can be executed at a time.
551
+ * Function are executed in the same order as `executeSynchronized` is called.
552
+ * WARNING: Calling `executeSynchronized` inside of `executeSynchronized` on the same lock instance is a deadlock.
553
+ */
554
+ async executeSynchronized(fun) {
555
+ const guard = await this.acquire();
556
+ try {
557
+ return await fun();
558
+ } finally {
559
+ guard.release();
560
+ }
561
+ }
562
+ };
563
+ var MutexGuard = class {
564
+ constructor(_release) {
565
+ this._release = _release;
566
+ }
567
+ /**
568
+ * Releases the lock.
569
+ */
570
+ release() {
571
+ this._release();
572
+ }
573
+ [Symbol.dispose]() {
574
+ this.release();
575
+ }
576
+ };
577
+ var classMutexSymbol = Symbol("class-mutex");
578
+ var FORCE_DISABLE_WARNING = false;
579
+ var enableWarning = !FORCE_DISABLE_WARNING && globalThis.mochaExecutor;
580
+ var synchronized = (target, propertyName, descriptor) => {
581
+ const method = descriptor.value;
582
+ descriptor.value = async function synchronizedMethod(...args) {
583
+ const mutex = this[classMutexSymbol] ??= new Mutex();
584
+ const tag = `${target.constructor.name}.${propertyName}`;
585
+ let guard;
586
+ if (!enableWarning) {
587
+ guard = await mutex.acquire(tag);
588
+ } else {
589
+ guard = await warnAfterTimeout(1e4, `lock on ${tag} (taken by ${mutex.tag})`, () => mutex.acquire(tag));
590
+ }
591
+ try {
592
+ return await method.apply(this, args);
593
+ } finally {
594
+ guard.release();
595
+ }
596
+ };
597
+ Object.defineProperty(descriptor.value, "name", {
598
+ value: propertyName + "$synchronized"
599
+ });
600
+ };
601
+
510
602
  // packages/common/async/src/observable.ts
511
603
  import Observable from "zen-observable";
512
604
  import PushStream from "zen-push";
@@ -752,97 +844,335 @@ var CancellableObservableProvider = class extends ObservableProvider {
752
844
  }
753
845
  };
754
846
 
755
- // packages/common/async/src/mutex.ts
756
- import "@dxos/util";
757
- import { warnAfterTimeout } from "@dxos/debug";
758
- var Mutex = class {
759
- constructor() {
760
- this._queue = Promise.resolve();
761
- this._queueLength = 0;
762
- this._tag = null;
847
+ // packages/common/async/src/persistent-lifecycle.ts
848
+ import { LifecycleState, Resource, cancelWithContext } from "@dxos/context";
849
+ import { warnAfterTimeout as warnAfterTimeout2 } from "@dxos/debug";
850
+ import { log as log2 } from "@dxos/log";
851
+
852
+ // packages/common/async/src/task-scheduling.ts
853
+ import { ContextDisposedError as ContextDisposedError2 } from "@dxos/context";
854
+ import { StackTrace as StackTrace2 } from "@dxos/debug";
855
+
856
+ // packages/common/async/src/track-leaks.ts
857
+ import { StackTrace } from "@dxos/debug";
858
+ import { log } from "@dxos/log";
859
+ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/common/async/src/track-leaks.ts";
860
+ var enabled = typeof process !== "undefined" && !!process.env.DX_TRACK_LEAKS;
861
+ var openResources = /* @__PURE__ */ new Set();
862
+ var handleSymbol = Symbol("checkLeaksHandle");
863
+ var trackResource = (resourceProvider) => {
864
+ if (!enabled) {
865
+ return () => {
866
+ };
763
867
  }
764
- get tag() {
765
- return this._tag;
868
+ const resource = resourceProvider();
869
+ openResources.add(resource);
870
+ return () => {
871
+ openResources.delete(resource);
872
+ };
873
+ };
874
+ var trackLeaks = (open, close) => (target) => {
875
+ if (!enabled) {
876
+ return;
766
877
  }
767
- isLocked() {
768
- return this._queueLength > 0;
878
+ const openMethod = target.prototype[open];
879
+ const closeMethod = target.prototype[close];
880
+ if (!openMethod || !closeMethod) {
881
+ throw new Error(`Cannot find ${open} or ${close} method in ${target.name}`);
882
+ }
883
+ {
884
+ target.prototype[open] = async function(...args) {
885
+ this[handleSymbol] = trackResource(() => ({
886
+ name: target.name,
887
+ openStack: new StackTrace()
888
+ }));
889
+ return openMethod.apply(this, args);
890
+ };
891
+ Object.defineProperty(target.prototype[open], "name", {
892
+ value: open + "$checkLeaks"
893
+ });
894
+ }
895
+ {
896
+ target.prototype[close] = async function(...args) {
897
+ this[handleSymbol]?.();
898
+ return closeMethod.apply(this, args);
899
+ };
900
+ Object.defineProperty(target.prototype[close], "name", {
901
+ value: close + "$checkLeaks"
902
+ });
903
+ }
904
+ };
905
+ var dumpLeaks = () => {
906
+ if (!enabled) {
907
+ return;
908
+ }
909
+ log.info(`Leaked resources ${openResources.size}:`, void 0, {
910
+ F: __dxlog_file3,
911
+ L: 82,
912
+ S: void 0,
913
+ C: (f, a) => f(...a)
914
+ });
915
+ for (const resource of openResources) {
916
+ log.info(`- ${resource.name} at`, void 0, {
917
+ F: __dxlog_file3,
918
+ L: 84,
919
+ S: void 0,
920
+ C: (f, a) => f(...a)
921
+ });
922
+ log.info(resource.openStack.getStack(1), void 0, {
923
+ F: __dxlog_file3,
924
+ L: 85,
925
+ S: void 0,
926
+ C: (f, a) => f(...a)
927
+ });
928
+ log.info("\n", void 0, {
929
+ F: __dxlog_file3,
930
+ L: 86,
931
+ S: void 0,
932
+ C: (f, a) => f(...a)
933
+ });
934
+ }
935
+ };
936
+ if (enabled) {
937
+ global.dxDumpLeaks = dumpLeaks;
938
+ }
939
+
940
+ // packages/common/async/src/task-scheduling.ts
941
+ var DeferredTask = class {
942
+ constructor(_ctx, _callback) {
943
+ this._ctx = _ctx;
944
+ this._callback = _callback;
945
+ this._scheduled = false;
946
+ this._currentTask = null;
947
+ this._nextTask = new Trigger();
948
+ }
949
+ get scheduled() {
950
+ return this._scheduled;
769
951
  }
770
952
  /**
771
- * Acquires the lock.
772
- * Caller is responsible for releasing the lock using the returned callback.
773
- * NOTE: Using `executeSynchronized` is preferred over using `acquire` directly.
774
- * @returns Release callback
953
+ * Schedule the task to run asynchronously.
775
954
  */
776
- async acquire(tag) {
777
- const prev = this._queue;
778
- let guard;
779
- this._queueLength++;
780
- this._queue = new Promise((resolve) => {
781
- guard = new MutexGuard(() => {
782
- this._queueLength--;
783
- this._tag = null;
784
- resolve();
955
+ schedule() {
956
+ if (this._scheduled) {
957
+ return;
958
+ }
959
+ scheduleTask(this._ctx, async () => {
960
+ await this._currentTask;
961
+ this._scheduled = false;
962
+ const completionTrigger = this._nextTask;
963
+ this._nextTask = new Trigger();
964
+ this._currentTask = runInContextAsync(this._ctx, () => this._callback()).then(() => {
965
+ completionTrigger.wake();
785
966
  });
786
967
  });
787
- await prev;
788
- if (tag !== void 0) {
789
- this._tag = tag;
790
- }
791
- return guard;
968
+ this._scheduled = true;
792
969
  }
793
970
  /**
794
- * Waits for all previous executions to complete and then executes a given function.
795
- * Only a single function can be executed at a time.
796
- * Function are executed in the same order as `executeSynchronized` is called.
797
- * WARNING: Calling `executeSynchronized` inside of `executeSynchronized` on the same lock instance is a deadlock.
971
+ * Schedule the task to run and wait for it to finish.
798
972
  */
799
- async executeSynchronized(fun) {
800
- const guard = await this.acquire();
801
- try {
802
- return await fun();
803
- } finally {
804
- guard.release();
973
+ async runBlocking() {
974
+ if (this._ctx.disposed) {
975
+ throw new ContextDisposedError2();
805
976
  }
806
- }
807
- };
808
- var MutexGuard = class {
809
- constructor(_release) {
810
- this._release = _release;
977
+ this.schedule();
978
+ await this._nextTask.wait();
811
979
  }
812
980
  /**
813
- * Releases the lock.
814
- */
815
- release() {
816
- this._release();
981
+ * Waits for the current task to finish if it is running.
982
+ * Does not schedule a new task.
983
+ */
984
+ async join() {
985
+ await this._currentTask;
817
986
  }
818
- [Symbol.dispose]() {
819
- this.release();
987
+ };
988
+ var runInContext = (ctx, fn) => {
989
+ try {
990
+ fn();
991
+ } catch (err) {
992
+ ctx.raise(err);
820
993
  }
821
994
  };
822
- var classMutexSymbol = Symbol("class-mutex");
823
- var FORCE_DISABLE_WARNING = false;
824
- var enableWarning = !FORCE_DISABLE_WARNING && globalThis.mochaExecutor;
825
- var synchronized = (target, propertyName, descriptor) => {
826
- const method = descriptor.value;
827
- descriptor.value = async function synchronizedMethod(...args) {
828
- const mutex = this[classMutexSymbol] ??= new Mutex();
829
- const tag = `${target.constructor.name}.${propertyName}`;
830
- let guard;
831
- if (!enableWarning) {
832
- guard = await mutex.acquire(tag);
833
- } else {
834
- guard = await warnAfterTimeout(1e4, `lock on ${tag} (taken by ${mutex.tag})`, () => mutex.acquire(tag));
995
+ var runInContextAsync = async (ctx, fn) => {
996
+ try {
997
+ await fn();
998
+ } catch (err) {
999
+ ctx.raise(err);
1000
+ }
1001
+ };
1002
+ var scheduleMicroTask = (ctx, fn) => {
1003
+ queueMicrotask(async () => {
1004
+ if (ctx.disposed) {
1005
+ return;
835
1006
  }
836
- try {
837
- return await method.apply(this, args);
838
- } finally {
839
- guard.release();
1007
+ await runInContextAsync(ctx, fn);
1008
+ });
1009
+ };
1010
+ var scheduleTask = (ctx, fn, afterMs) => {
1011
+ const clearTracking = trackResource(() => ({
1012
+ name: `task (${fn.name || "anonymous"})`,
1013
+ openStack: new StackTrace2()
1014
+ }));
1015
+ const timeout = setTimeout(async () => {
1016
+ clearDispose();
1017
+ await runInContextAsync(ctx, fn);
1018
+ clearTracking();
1019
+ }, afterMs);
1020
+ const clearDispose = ctx.onDispose(() => {
1021
+ clearTracking();
1022
+ clearTimeout(timeout);
1023
+ });
1024
+ };
1025
+ var scheduleTaskInterval = (ctx, task, interval) => {
1026
+ const clearTracking = trackResource(() => ({
1027
+ name: `repeating task (${task.name || "anonymous"})`,
1028
+ openStack: new StackTrace2()
1029
+ }));
1030
+ let timeoutId;
1031
+ const run = async () => {
1032
+ await runInContextAsync(ctx, task);
1033
+ if (ctx.disposed) {
1034
+ return;
840
1035
  }
1036
+ timeoutId = setTimeout(run, interval);
841
1037
  };
842
- Object.defineProperty(descriptor.value, "name", {
843
- value: propertyName + "$synchronized"
1038
+ timeoutId = setTimeout(run, interval);
1039
+ ctx.onDispose(() => {
1040
+ clearTracking();
1041
+ clearTimeout(timeoutId);
844
1042
  });
845
1043
  };
1044
+ var scheduleExponentialBackoffTaskInterval = (ctx, task, initialInterval) => {
1045
+ const clearTracking = trackResource(() => ({
1046
+ name: `repeating task (${task.name || "anonymous"})`,
1047
+ openStack: new StackTrace2()
1048
+ }));
1049
+ let timeoutId;
1050
+ let interval = initialInterval;
1051
+ const repeat = async () => {
1052
+ await runInContextAsync(ctx, task);
1053
+ if (ctx.disposed) {
1054
+ return;
1055
+ }
1056
+ interval *= 2;
1057
+ timeoutId = setTimeout(repeat, interval);
1058
+ };
1059
+ timeoutId = setTimeout(repeat, interval);
1060
+ ctx.onDispose(() => {
1061
+ clearTracking();
1062
+ clearTimeout(timeoutId);
1063
+ });
1064
+ };
1065
+
1066
+ // packages/common/async/src/persistent-lifecycle.ts
1067
+ function _ts_decorate(decorators, target, key, desc) {
1068
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1069
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1070
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1071
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1072
+ }
1073
+ var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/common/async/src/persistent-lifecycle.ts";
1074
+ var INIT_RESTART_DELAY = 100;
1075
+ var DEFAULT_MAX_RESTART_DELAY = 5e3;
1076
+ var PersistentLifecycle = class extends Resource {
1077
+ constructor({ start, stop, onRestart, maxRestartDelay = DEFAULT_MAX_RESTART_DELAY }) {
1078
+ super();
1079
+ this._currentState = void 0;
1080
+ this._restartTask = void 0;
1081
+ this._restartAfter = 0;
1082
+ this._start = start;
1083
+ this._stop = stop;
1084
+ this._onRestart = onRestart;
1085
+ this._maxRestartDelay = maxRestartDelay;
1086
+ }
1087
+ get state() {
1088
+ return this._currentState;
1089
+ }
1090
+ async _open() {
1091
+ this._restartTask = new DeferredTask(this._ctx, async () => {
1092
+ try {
1093
+ await this._restart();
1094
+ } catch (err) {
1095
+ log2.warn("Restart failed", {
1096
+ err
1097
+ }, {
1098
+ F: __dxlog_file4,
1099
+ L: 72,
1100
+ S: this,
1101
+ C: (f, a) => f(...a)
1102
+ });
1103
+ this._restartTask?.schedule();
1104
+ }
1105
+ });
1106
+ this._currentState = await this._start().catch((err) => {
1107
+ log2.warn("Start failed", {
1108
+ err
1109
+ }, {
1110
+ F: __dxlog_file4,
1111
+ L: 77,
1112
+ S: this,
1113
+ C: (f, a) => f(...a)
1114
+ });
1115
+ this._restartTask?.schedule();
1116
+ return void 0;
1117
+ });
1118
+ }
1119
+ async _close() {
1120
+ await this._restartTask?.join();
1121
+ await this._stopCurrentState();
1122
+ this._restartTask = void 0;
1123
+ }
1124
+ async _restart() {
1125
+ log2(`restarting in ${this._restartAfter}ms`, {
1126
+ state: this._lifecycleState
1127
+ }, {
1128
+ F: __dxlog_file4,
1129
+ L: 90,
1130
+ S: this,
1131
+ C: (f, a) => f(...a)
1132
+ });
1133
+ await this._stopCurrentState();
1134
+ if (this._lifecycleState !== LifecycleState.OPEN) {
1135
+ return;
1136
+ }
1137
+ await cancelWithContext(this._ctx, sleep(this._restartAfter));
1138
+ this._restartAfter = Math.min(Math.max(this._restartAfter * 2, INIT_RESTART_DELAY), this._maxRestartDelay);
1139
+ await warnAfterTimeout2(5e3, "Connection establishment takes too long", async () => {
1140
+ this._currentState = await this._start();
1141
+ });
1142
+ this._restartAfter = 0;
1143
+ await this._onRestart?.();
1144
+ }
1145
+ async _stopCurrentState() {
1146
+ if (this._currentState) {
1147
+ try {
1148
+ await this._stop(this._currentState);
1149
+ } catch (err) {
1150
+ log2.catch(err, void 0, {
1151
+ F: __dxlog_file4,
1152
+ L: 112,
1153
+ S: this,
1154
+ C: (f, a) => f(...a)
1155
+ });
1156
+ }
1157
+ this._currentState = void 0;
1158
+ }
1159
+ }
1160
+ /**
1161
+ * Scheduling restart should be done from outside.
1162
+ */
1163
+ scheduleRestart() {
1164
+ if (this._lifecycleState !== LifecycleState.OPEN) {
1165
+ return;
1166
+ }
1167
+ this._restartTask.schedule();
1168
+ }
1169
+ };
1170
+ _ts_decorate([
1171
+ synchronized
1172
+ ], PersistentLifecycle.prototype, "_open", null);
1173
+ _ts_decorate([
1174
+ synchronized
1175
+ ], PersistentLifecycle.prototype, "scheduleRestart", null);
846
1176
 
847
1177
  // packages/common/async/src/sink.ts
848
1178
  var sink = (emitter, event, count = 1) => {
@@ -900,6 +1230,63 @@ var streamToArray = (stream) => {
900
1230
  return deferred;
901
1231
  };
902
1232
 
1233
+ // packages/common/async/src/test-stream.ts
1234
+ import { Duplex } from "node:stream";
1235
+ var TestStream = class extends Duplex {
1236
+ constructor() {
1237
+ super(...arguments);
1238
+ this._received = Buffer.alloc(0);
1239
+ this._onWrite = new Event();
1240
+ }
1241
+ static async assertConnectivity(stream1, stream2, { timeout = 200 } = {}) {
1242
+ stream1.push("ping");
1243
+ stream2.push("pong");
1244
+ await Promise.all([
1245
+ stream2.assertReceivedAsync("ping", {
1246
+ timeout
1247
+ }),
1248
+ stream1.assertReceivedAsync("pong", {
1249
+ timeout
1250
+ })
1251
+ ]);
1252
+ }
1253
+ _write(chunk, encoding, callback) {
1254
+ this._received = Buffer.concat([
1255
+ this._received,
1256
+ chunk
1257
+ ]);
1258
+ this._onWrite.emit();
1259
+ callback();
1260
+ }
1261
+ _read(size) {
1262
+ }
1263
+ assertReceivedAsync(data, { timeout = 200 } = {}) {
1264
+ const dataBuffer = Buffer.isBuffer(data) ? data : Buffer.from(data);
1265
+ return asyncTimeout(this._onWrite.waitForCondition(() => this._received.equals(dataBuffer)), timeout);
1266
+ }
1267
+ };
1268
+
1269
+ // packages/common/async/src/testing.ts
1270
+ var waitForCondition = ({ condition, timeout = 0, interval = 10, error }) => {
1271
+ const stopTime = timeout ? Date.now() + timeout : 0;
1272
+ const trigger2 = new Trigger();
1273
+ const waiter = async () => {
1274
+ while (!stopTime || Date.now() < stopTime) {
1275
+ try {
1276
+ const value = await condition();
1277
+ if (value) {
1278
+ trigger2.wake(value);
1279
+ break;
1280
+ }
1281
+ } catch (err) {
1282
+ }
1283
+ await sleep(interval);
1284
+ }
1285
+ };
1286
+ setTimeout(waiter, 0);
1287
+ return timeout ? asyncTimeout(trigger2.wait(), timeout, error ?? new Error("Timeout")) : trigger2.wait();
1288
+ };
1289
+
903
1290
  // packages/common/async/src/timer.ts
904
1291
  var Timer = class {
905
1292
  constructor(_callback) {
@@ -948,27 +1335,6 @@ var Timer = class {
948
1335
  }
949
1336
  };
950
1337
 
951
- // packages/common/async/src/testing.ts
952
- var waitForCondition = ({ condition, timeout = 0, interval = 10, error }) => {
953
- const stopTime = timeout ? Date.now() + timeout : 0;
954
- const trigger2 = new Trigger();
955
- const waiter = async () => {
956
- while (!stopTime || Date.now() < stopTime) {
957
- try {
958
- const value = await condition();
959
- if (value) {
960
- trigger2.wake(value);
961
- break;
962
- }
963
- } catch (err) {
964
- }
965
- await sleep(interval);
966
- }
967
- };
968
- setTimeout(waiter, 0);
969
- return timeout ? asyncTimeout(trigger2.wait(), timeout, error ?? new Error("Timeout")) : trigger2.wait();
970
- };
971
-
972
1338
  // packages/common/async/src/until.ts
973
1339
  var until = (cb, timeout) => {
974
1340
  return new Promise((resolve, reject) => {
@@ -1004,256 +1370,6 @@ var untilError = (cb) => {
1004
1370
  });
1005
1371
  };
1006
1372
 
1007
- // packages/common/async/src/task-scheduling.ts
1008
- import { ContextDisposedError as ContextDisposedError2 } from "@dxos/context";
1009
- import { StackTrace as StackTrace2 } from "@dxos/debug";
1010
-
1011
- // packages/common/async/src/track-leaks.ts
1012
- import { StackTrace } from "@dxos/debug";
1013
- import { log } from "@dxos/log";
1014
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/common/async/src/track-leaks.ts";
1015
- var enabled = typeof process !== "undefined" && !!process.env.DX_TRACK_LEAKS;
1016
- var openResources = /* @__PURE__ */ new Set();
1017
- var handleSymbol = Symbol("checkLeaksHandle");
1018
- var trackResource = (resourceProvider) => {
1019
- if (!enabled) {
1020
- return () => {
1021
- };
1022
- }
1023
- const resource = resourceProvider();
1024
- openResources.add(resource);
1025
- return () => {
1026
- openResources.delete(resource);
1027
- };
1028
- };
1029
- var trackLeaks = (open, close) => (target) => {
1030
- if (!enabled) {
1031
- return;
1032
- }
1033
- const openMethod = target.prototype[open];
1034
- const closeMethod = target.prototype[close];
1035
- if (!openMethod || !closeMethod) {
1036
- throw new Error(`Cannot find ${open} or ${close} method in ${target.name}`);
1037
- }
1038
- {
1039
- target.prototype[open] = async function(...args) {
1040
- this[handleSymbol] = trackResource(() => ({
1041
- name: target.name,
1042
- openStack: new StackTrace()
1043
- }));
1044
- return openMethod.apply(this, args);
1045
- };
1046
- Object.defineProperty(target.prototype[open], "name", {
1047
- value: open + "$checkLeaks"
1048
- });
1049
- }
1050
- {
1051
- target.prototype[close] = async function(...args) {
1052
- this[handleSymbol]?.();
1053
- return closeMethod.apply(this, args);
1054
- };
1055
- Object.defineProperty(target.prototype[close], "name", {
1056
- value: close + "$checkLeaks"
1057
- });
1058
- }
1059
- };
1060
- var dumpLeaks = () => {
1061
- if (!enabled) {
1062
- return;
1063
- }
1064
- log.info(`Leaked resources ${openResources.size}:`, void 0, {
1065
- F: __dxlog_file3,
1066
- L: 82,
1067
- S: void 0,
1068
- C: (f, a) => f(...a)
1069
- });
1070
- for (const resource of openResources) {
1071
- log.info(`- ${resource.name} at`, void 0, {
1072
- F: __dxlog_file3,
1073
- L: 84,
1074
- S: void 0,
1075
- C: (f, a) => f(...a)
1076
- });
1077
- log.info(resource.openStack.getStack(1), void 0, {
1078
- F: __dxlog_file3,
1079
- L: 85,
1080
- S: void 0,
1081
- C: (f, a) => f(...a)
1082
- });
1083
- log.info("\n", void 0, {
1084
- F: __dxlog_file3,
1085
- L: 86,
1086
- S: void 0,
1087
- C: (f, a) => f(...a)
1088
- });
1089
- }
1090
- };
1091
- if (enabled) {
1092
- global.dxDumpLeaks = dumpLeaks;
1093
- }
1094
-
1095
- // packages/common/async/src/task-scheduling.ts
1096
- var DeferredTask = class {
1097
- constructor(_ctx, _callback) {
1098
- this._ctx = _ctx;
1099
- this._callback = _callback;
1100
- this._scheduled = false;
1101
- this._currentTask = null;
1102
- this._nextTask = new Trigger();
1103
- }
1104
- get scheduled() {
1105
- return this._scheduled;
1106
- }
1107
- /**
1108
- * Schedule the task to run asynchronously.
1109
- */
1110
- schedule() {
1111
- if (this._scheduled) {
1112
- return;
1113
- }
1114
- scheduleTask(this._ctx, async () => {
1115
- await this._currentTask;
1116
- this._scheduled = false;
1117
- const completionTrigger = this._nextTask;
1118
- this._nextTask = new Trigger();
1119
- this._currentTask = runInContextAsync(this._ctx, () => this._callback()).then(() => {
1120
- completionTrigger.wake();
1121
- });
1122
- });
1123
- this._scheduled = true;
1124
- }
1125
- /**
1126
- * Schedule the task to run and wait for it to finish.
1127
- */
1128
- async runBlocking() {
1129
- if (this._ctx.disposed) {
1130
- throw new ContextDisposedError2();
1131
- }
1132
- this.schedule();
1133
- await this._nextTask.wait();
1134
- }
1135
- /**
1136
- * Waits for the current task to finish if it is running.
1137
- * Does not schedule a new task.
1138
- */
1139
- async join() {
1140
- await this._currentTask;
1141
- }
1142
- };
1143
- var runInContext = (ctx, fn) => {
1144
- try {
1145
- fn();
1146
- } catch (err) {
1147
- ctx.raise(err);
1148
- }
1149
- };
1150
- var runInContextAsync = async (ctx, fn) => {
1151
- try {
1152
- await fn();
1153
- } catch (err) {
1154
- ctx.raise(err);
1155
- }
1156
- };
1157
- var scheduleMicroTask = (ctx, fn) => {
1158
- queueMicrotask(async () => {
1159
- if (ctx.disposed) {
1160
- return;
1161
- }
1162
- await runInContextAsync(ctx, fn);
1163
- });
1164
- };
1165
- var scheduleTask = (ctx, fn, afterMs) => {
1166
- const clearTracking = trackResource(() => ({
1167
- name: `task (${fn.name || "anonymous"})`,
1168
- openStack: new StackTrace2()
1169
- }));
1170
- const timeout = setTimeout(async () => {
1171
- clearDispose();
1172
- await runInContextAsync(ctx, fn);
1173
- clearTracking();
1174
- }, afterMs);
1175
- const clearDispose = ctx.onDispose(() => {
1176
- clearTracking();
1177
- clearTimeout(timeout);
1178
- });
1179
- };
1180
- var scheduleTaskInterval = (ctx, task, interval) => {
1181
- const clearTracking = trackResource(() => ({
1182
- name: `repeating task (${task.name || "anonymous"})`,
1183
- openStack: new StackTrace2()
1184
- }));
1185
- let timeoutId;
1186
- const run = async () => {
1187
- await runInContextAsync(ctx, task);
1188
- if (ctx.disposed) {
1189
- return;
1190
- }
1191
- timeoutId = setTimeout(run, interval);
1192
- };
1193
- timeoutId = setTimeout(run, interval);
1194
- ctx.onDispose(() => {
1195
- clearTracking();
1196
- clearTimeout(timeoutId);
1197
- });
1198
- };
1199
- var scheduleExponentialBackoffTaskInterval = (ctx, task, initialInterval) => {
1200
- const clearTracking = trackResource(() => ({
1201
- name: `repeating task (${task.name || "anonymous"})`,
1202
- openStack: new StackTrace2()
1203
- }));
1204
- let timeoutId;
1205
- let interval = initialInterval;
1206
- const repeat = async () => {
1207
- await runInContextAsync(ctx, task);
1208
- if (ctx.disposed) {
1209
- return;
1210
- }
1211
- interval *= 2;
1212
- timeoutId = setTimeout(repeat, interval);
1213
- };
1214
- timeoutId = setTimeout(repeat, interval);
1215
- ctx.onDispose(() => {
1216
- clearTracking();
1217
- clearTimeout(timeoutId);
1218
- });
1219
- };
1220
-
1221
- // packages/common/async/src/test-stream.ts
1222
- import { Duplex } from "node:stream";
1223
- var TestStream = class extends Duplex {
1224
- constructor() {
1225
- super(...arguments);
1226
- this._received = Buffer.alloc(0);
1227
- this._onWrite = new Event();
1228
- }
1229
- static async assertConnectivity(stream1, stream2, { timeout = 200 } = {}) {
1230
- stream1.push("ping");
1231
- stream2.push("pong");
1232
- await Promise.all([
1233
- stream2.assertReceivedAsync("ping", {
1234
- timeout
1235
- }),
1236
- stream1.assertReceivedAsync("pong", {
1237
- timeout
1238
- })
1239
- ]);
1240
- }
1241
- _write(chunk, encoding, callback) {
1242
- this._received = Buffer.concat([
1243
- this._received,
1244
- chunk
1245
- ]);
1246
- this._onWrite.emit();
1247
- callback();
1248
- }
1249
- _read(size) {
1250
- }
1251
- assertReceivedAsync(data, { timeout = 200 } = {}) {
1252
- const dataBuffer = Buffer.isBuffer(data) ? data : Buffer.from(data);
1253
- return asyncTimeout(this._onWrite.waitForCondition(() => this._received.equals(dataBuffer)), timeout);
1254
- }
1255
- };
1256
-
1257
1373
  // packages/common/async/src/update-scheduler.ts
1258
1374
  var TIME_PERIOD = 1e3;
1259
1375
  var UpdateScheduler = class {
@@ -1335,6 +1451,7 @@ export {
1335
1451
  MutexGuard,
1336
1452
  Observable,
1337
1453
  ObservableProvider,
1454
+ PersistentLifecycle,
1338
1455
  PushStream,
1339
1456
  TestStream,
1340
1457
  TimeoutError,