@milaboratories/pl-tree 1.6.8 → 1.6.10

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.
@@ -97,11 +97,19 @@ export class SynchronizedTreeState {
97
97
  await this.hooks.refreshState();
98
98
  }
99
99
 
100
+ private currentLoopDelayInterrupt: AbortController | undefined = undefined;
100
101
  private scheduledOnNextState: ScheduledRefresh[] = [];
101
102
 
103
+ /** Called from computable hooks when external observer asks for state refresh */
102
104
  private scheduleOnNextState(resolve: () => void, reject: (err: any) => void): void {
103
105
  if (this.terminated) reject(new Error('tree synchronization is terminated'));
104
- else this.scheduledOnNextState.push({ resolve, reject });
106
+ else {
107
+ this.scheduledOnNextState.push({ resolve, reject });
108
+ if (this.currentLoopDelayInterrupt) {
109
+ this.currentLoopDelayInterrupt.abort();
110
+ this.currentLoopDelayInterrupt = undefined;
111
+ }
112
+ }
105
113
  }
106
114
 
107
115
  /** Called from observer */
@@ -138,8 +146,10 @@ export class SynchronizedTreeState {
138
146
  // will hold request stats
139
147
  let stat = this.logStat ? initialTreeLoadingStat() : undefined;
140
148
 
149
+ let lastUpdate = Date.now();
150
+
141
151
  while (true) {
142
- if (!this.keepRunning) break;
152
+ if (!this.keepRunning || this.terminated) break;
143
153
 
144
154
  // saving those who want to be notified about new state here
145
155
  // because those who will be added during the tree retrieval
@@ -158,13 +168,15 @@ export class SynchronizedTreeState {
158
168
  await this.refresh(stat);
159
169
 
160
170
  // logging stats if we were asked to
161
- if (stat && this.logger) this.logger.info(`Tree stat (success): ${JSON.stringify(stat)}`);
171
+ if (stat && this.logger) this.logger.info(`Tree stat (success, after ${Date.now() - lastUpdate}ms): ${JSON.stringify(stat)}`);
172
+ lastUpdate = Date.now();
162
173
 
163
174
  // notifying that we got new state
164
175
  if (toNotify !== undefined) for (const n of toNotify) n.resolve();
165
176
  } catch (e: any) {
166
177
  // logging stats if we were asked to (even if error occured)
167
- if (stat && this.logger) this.logger.info(`Tree stat (error): ${JSON.stringify(stat)}`);
178
+ if (stat && this.logger) this.logger.info(`Tree stat (error, after ${Date.now() - lastUpdate}ms): ${JSON.stringify(stat)}`);
179
+ lastUpdate = Date.now();
168
180
 
169
181
  // notifying that we failed to refresh the state
170
182
  if (toNotify !== undefined) for (const n of toNotify) n.reject(e);
@@ -191,11 +203,17 @@ export class SynchronizedTreeState {
191
203
 
192
204
  if (!this.keepRunning || this.terminated) break;
193
205
 
194
- try {
195
- await tp.setTimeout(this.pollingInterval, this.abortController.signal);
196
- } catch (e: unknown) {
197
- if (!isTimeoutOrCancelError(e)) throw new Error('Unexpected error', { cause: e });
198
- break;
206
+ if (this.scheduledOnNextState.length === 0) {
207
+ try {
208
+ this.currentLoopDelayInterrupt = new AbortController();
209
+ await tp.setTimeout(this.pollingInterval,
210
+ AbortSignal.any([this.abortController.signal, this.currentLoopDelayInterrupt.signal]));
211
+ } catch (e: unknown) {
212
+ if (!isTimeoutOrCancelError(e)) throw new Error('Unexpected error', { cause: e });
213
+ break;
214
+ } finally {
215
+ this.currentLoopDelayInterrupt = undefined;
216
+ }
199
217
  }
200
218
  }
201
219