@x-oasis/integer-buffer-set 0.1.27 → 0.1.29

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/src/index.ts CHANGED
@@ -16,6 +16,8 @@ import {
16
16
  const defaultMetaExtractor = (value) => value;
17
17
  export const defaultBufferSize = 10;
18
18
  const thresholdNumber = Number.MAX_SAFE_INTEGER - 100000;
19
+ const assertThresholdNumber = (val: any) =>
20
+ typeof val === 'number' && val > thresholdNumber;
19
21
 
20
22
  // !!!!! should do meta validation...meta should has an index...
21
23
  // value: original data `index` value
@@ -98,11 +100,6 @@ class IntegerBufferSet<Meta = any> {
98
100
  return this._bufferSize;
99
101
  }
100
102
 
101
- isThresholdMeta(meta) {
102
- if (typeof meta === 'number' && meta > thresholdNumber) return true;
103
- return false;
104
- }
105
-
106
103
  setIsOnTheFlyFull(val: any) {
107
104
  if (val != null) {
108
105
  const data = this._onTheFlyIndices.filter((v) => v != null);
@@ -140,15 +137,23 @@ class IntegerBufferSet<Meta = any> {
140
137
  }
141
138
 
142
139
  getIndexMeta(index: number) {
143
- if (index == null || index < 0) return null;
144
- return this._metaExtractor(index);
140
+ try {
141
+ if (index == null || index < 0) return null;
142
+ return this._metaExtractor(index);
143
+ } catch (err) {
144
+ return null;
145
+ }
145
146
  }
146
147
 
147
148
  getMetaIndex(meta: Meta) {
148
- if (meta == null) return -1;
149
- if (this.isThresholdMeta(meta)) return -1;
150
- if (this._indexExtractor) return this._indexExtractor(meta);
151
- return this._metaToIndexMap.get(meta);
149
+ try {
150
+ if (meta == null) return -1;
151
+ if (assertThresholdNumber(meta)) return -1;
152
+ if (this._indexExtractor) return this._indexExtractor(meta);
153
+ return this._metaToIndexMap.get(meta);
154
+ } catch (err) {
155
+ return -1;
156
+ }
152
157
  }
153
158
 
154
159
  setMetaIndex(meta: Meta, index: number) {
@@ -188,12 +193,63 @@ class IntegerBufferSet<Meta = any> {
188
193
  return newPosition;
189
194
  }
190
195
 
191
- getMinValue() {
192
- return this._smallValues.peek()?.value;
196
+ _peek(heap: Heap) {
197
+ return heap.peek();
198
+ }
199
+
200
+ _getMaxItem() {
201
+ return this._peek(this._largeValues);
193
202
  }
194
203
 
204
+ _getMinItem() {
205
+ return this._peek(this._smallValues);
206
+ }
207
+
208
+ _getMinValue() {
209
+ return this._peek(this._smallValues)?.value;
210
+ }
211
+
212
+ _getMaxValue() {
213
+ return this._peek(this._largeValues)?.value;
214
+ }
215
+
216
+ // should omit thresholdNumber
195
217
  getMaxValue() {
196
- return this._largeValues.peek()?.value;
218
+ const stack = [];
219
+ let item;
220
+
221
+ while ((item = this._getMaxItem()) && assertThresholdNumber(item?.value)) {
222
+ stack.push(item);
223
+ this._largeValues.pop();
224
+ }
225
+
226
+ let stackItem;
227
+ while ((stackItem = stack.pop())) {
228
+ this._largeValues.push(stackItem);
229
+ }
230
+
231
+ return item?.value;
232
+ }
233
+
234
+ getMinValue() {
235
+ const stack = [];
236
+ let item;
237
+
238
+ while ((item = this._getMinItem()) && assertThresholdNumber(item?.value)) {
239
+ stack.push(item);
240
+ this._smallValues.pop();
241
+ }
242
+
243
+ let stackItem;
244
+ while ((stackItem = stack.pop())) {
245
+ this._smallValues.push(stackItem);
246
+ }
247
+
248
+ return item?.value;
249
+ }
250
+
251
+ _push(heap: Heap, item: HeapItem) {
252
+ heap.push(item);
197
253
  }
198
254
 
199
255
  getFliedPosition(newIndex: number, safeRange: SafeRange) {
@@ -268,7 +324,6 @@ class IntegerBufferSet<Meta = any> {
268
324
  });
269
325
  } else {
270
326
  this._cleanHeaps();
271
- // console.log('commeit ---')
272
327
  position = this.commitPosition({
273
328
  newIndex,
274
329
  meta,
@@ -325,11 +380,10 @@ class IntegerBufferSet<Meta = any> {
325
380
 
326
381
  let indexToReplace;
327
382
 
328
- const minValue = this._smallValues.peek()!.value;
329
- const maxValue = this._largeValues.peek()!.value;
383
+ const minValue = this._getMinValue();
384
+ const maxValue = this._getMaxValue();
330
385
 
331
- // console.log('mathc ', maxValue, maxValue > thresholdNumber)
332
- if (maxValue > thresholdNumber) {
386
+ if (assertThresholdNumber(maxValue)) {
333
387
  indexToReplace = maxValue;
334
388
  this._largeValues.pop();
335
389
  const replacedMeta = this._indexToMetaMap.get(indexToReplace);
@@ -390,7 +444,7 @@ class IntegerBufferSet<Meta = any> {
390
444
  return position;
391
445
  }
392
446
 
393
- shuffle() {
447
+ shuffle(options: { retry: boolean; fallback: boolean }) {
394
448
  const indices = new Array(this.bufferSize);
395
449
  for (let idx = 0; idx < indices.length; idx++) {
396
450
  const meta = this._onTheFlyIndices[idx] || this._positionToMetaList[idx];
@@ -448,33 +502,43 @@ class IntegerBufferSet<Meta = any> {
448
502
 
449
503
  this._positionToMetaList = positionToMetaList;
450
504
 
451
- return this.getIndices();
505
+ return this.getIndices({
506
+ ...options,
507
+ retry: true,
508
+ });
452
509
  }
453
510
 
454
511
  // key point: `meta` should be preserved..
455
- getIndices() {
456
- const { smallValues, largeValues } = this.initialize();
457
-
512
+ getIndices(
513
+ options = {
514
+ retry: false,
515
+ fallback: false,
516
+ }
517
+ ) {
458
518
  try {
519
+ const { retry, fallback } = options;
520
+ const { smallValues, largeValues } = this.initialize();
459
521
  const indices = new Array(this._positionToMetaList.length);
460
522
  const metaToPositionMap = new Map();
461
523
  const indexToMetaMap = new Map();
462
524
  const metaToIndexMap = new Map();
463
525
  for (let idx = 0; idx < indices.length; idx++) {
464
- const meta =
465
- this._onTheFlyIndices[idx] || this._positionToMetaList[idx];
526
+ const meta = fallback
527
+ ? this._onTheFlyIndices[idx]
528
+ : this._onTheFlyIndices[idx] || this._positionToMetaList[idx];
466
529
  const targetIndex = this.getMetaIndex(meta);
467
- // which means source data has changed. such as one element has been deleted
530
+ // which means source data has changed. such as one item has been deleted
468
531
  if (
469
- !this.isThresholdMeta(meta) &&
470
- meta != this.getIndexMeta(targetIndex)
532
+ !assertThresholdNumber(meta) &&
533
+ meta != this.getIndexMeta(targetIndex) &&
534
+ !retry
471
535
  ) {
472
- return this.shuffle();
536
+ return this.shuffle(options);
473
537
  }
474
- if (meta != null && !this.isThresholdMeta(meta)) {
475
- const element = { position: idx, value: targetIndex };
476
- smallValues.push(element);
477
- largeValues.push(element);
538
+ if (meta != null && !assertThresholdNumber(meta)) {
539
+ const item = { position: idx, value: targetIndex };
540
+ this._push(smallValues, item);
541
+ this._push(largeValues, item);
478
542
  metaToPositionMap.set(meta, idx);
479
543
  indexToMetaMap.set(targetIndex, meta);
480
544
  metaToIndexMap.set(meta, targetIndex);
@@ -496,7 +560,10 @@ class IntegerBufferSet<Meta = any> {
496
560
  return indices;
497
561
  } catch (err) {
498
562
  console.log('err ', err);
499
- return this._positionToMetaList;
563
+ return this.getIndices({
564
+ ...options,
565
+ fallback: true,
566
+ });
500
567
  } finally {
501
568
  this.readyToStartNextLoop();
502
569
  // clear on the fly indices after return indices.
@@ -504,10 +571,10 @@ class IntegerBufferSet<Meta = any> {
504
571
  }
505
572
 
506
573
  _pushToHeaps(position: number, value: number) {
507
- const element = { position, value };
574
+ const item = { position, value };
508
575
  // We can reuse the same object in both heaps, because we don't mutate them
509
- this._smallValues.push(element);
510
- this._largeValues.push(element);
576
+ this._push(this._smallValues, item);
577
+ this._push(this._largeValues, item);
511
578
  }
512
579
 
513
580
  _setMetaPosition(meta: Meta, position: number) {
@@ -528,8 +595,6 @@ class IntegerBufferSet<Meta = any> {
528
595
  const onTheFlyPositionMeta = this._onTheFlyIndices[position];
529
596
  let positionToReplace = position;
530
597
 
531
- // console.log('position ', newIndex, position);
532
-
533
598
  if (onTheFlyPositionMeta) {
534
599
  // such as place item 11 twice...
535
600
  if (onTheFlyPositionMeta === meta) return position;
@@ -581,11 +646,6 @@ class IntegerBufferSet<Meta = any> {
581
646
  }
582
647
 
583
648
  _cleanHeaps() {
584
- // We not usually only remove object from one heap while moving value.
585
- // Here we make sure that there is no stale data on top of heaps.
586
- // this._cleanHeap(this._smallValues);
587
- // this._cleanHeap(this._largeValues);
588
-
589
649
  for (let idx = 0; idx < this._positionToMetaList.length; idx++) {
590
650
  if (this._positionToMetaList[idx] == null) {
591
651
  this._recreateHeaps();
@@ -601,6 +661,8 @@ class IntegerBufferSet<Meta = any> {
601
661
  this._smallValues.size(),
602
662
  this._largeValues.size()
603
663
  );
664
+ // We not usually only remove object from one heap while moving value.
665
+ // Here we make sure that there is no stale data on top of heaps.
604
666
  if (maxHeapSize > 10 * minHeapSize) {
605
667
  // There are many old values in one of heaps. We need to get rid of them
606
668
  // to not use too avoid memory leaks
@@ -616,14 +678,13 @@ class IntegerBufferSet<Meta = any> {
616
678
  ) {
617
679
  const meta = this._positionToMetaList[position];
618
680
  let value = this.getMetaIndex(meta);
619
-
620
- if (!meta || value === -1 || value == null) {
681
+ if (meta == null || value === -1 || value == null) {
621
682
  value = Number.MAX_SAFE_INTEGER - position;
622
683
  }
623
684
 
624
- const element = { position, value };
625
- smallValues.push(element);
626
- largeValues.push(element);
685
+ const item = { position, value };
686
+ this._push(smallValues, item);
687
+ this._push(largeValues, item);
627
688
  if (value > thresholdNumber) {
628
689
  // @ts-ignore
629
690
  this._setMetaPosition(value, position);
@@ -631,25 +692,10 @@ class IntegerBufferSet<Meta = any> {
631
692
  this._setMetaIndex(value, value);
632
693
  }
633
694
  }
634
-
635
- // this._largeValues.peek().value;
636
-
637
695
  this._smallValues = smallValues;
638
696
  this._largeValues = largeValues;
639
697
  }
640
698
 
641
- // _cleanHeap(heap: Heap<HeapItem>) {
642
- // while (
643
- // !heap.empty() &&
644
- // this._metaToPositionMap.get(
645
- // this._indexToMetaMap.get(heap.peek()!.value)
646
- // ) == null
647
- // ) {
648
- // console.log('pop ---', heap.peek()!.value);
649
- // heap.pop();
650
- // }
651
- // }
652
-
653
699
  _smallerComparator(lhs: HeapItem, rhs: HeapItem) {
654
700
  return lhs.value < rhs.value;
655
701
  }