envio 2.31.0-alpha.0 → 2.31.0-alpha.2

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.
@@ -0,0 +1,132 @@
1
+ // We need this module to effectively track safe checkpoint id
2
+ // this is very cheap to do in memory, while requires a lot of work on a db
3
+ // especially when save_full_history is enabled.
4
+ // The safe checkpoint id can be used to optimize checkpoints traverse logic and
5
+ // make pruning operation super cheap.
6
+ type t = {
7
+ checkpointIds: array<int>,
8
+ checkpointBlockNumbers: array<int>,
9
+ maxReorgDepth: int,
10
+ }
11
+
12
+ let make = (
13
+ ~maxReorgDepth,
14
+ ~shouldRollbackOnReorg,
15
+ ~chainReorgCheckpoints: array<Internal.reorgCheckpoint>,
16
+ ) => {
17
+ if maxReorgDepth > 0 && shouldRollbackOnReorg {
18
+ let checkpointIds = Belt.Array.makeUninitializedUnsafe(chainReorgCheckpoints->Array.length)
19
+ let checkpointBlockNumbers = Belt.Array.makeUninitializedUnsafe(
20
+ chainReorgCheckpoints->Array.length,
21
+ )
22
+ chainReorgCheckpoints->Js.Array2.forEachi((checkpoint, idx) => {
23
+ checkpointIds->Belt.Array.setUnsafe(idx, checkpoint.checkpointId)
24
+ checkpointBlockNumbers->Belt.Array.setUnsafe(idx, checkpoint.blockNumber)
25
+ })
26
+ Some({
27
+ checkpointIds,
28
+ checkpointBlockNumbers,
29
+ maxReorgDepth,
30
+ })
31
+ } else {
32
+ None
33
+ }
34
+ }
35
+
36
+ let getSafeCheckpointId = (safeCheckpointTracking: t, ~sourceBlockNumber: int) => {
37
+ let safeBlockNumber = sourceBlockNumber - safeCheckpointTracking.maxReorgDepth
38
+
39
+ if safeCheckpointTracking.checkpointBlockNumbers->Belt.Array.getUnsafe(0) > safeBlockNumber {
40
+ 0
41
+ } else {
42
+ let trackingCheckpointsCount = safeCheckpointTracking.checkpointBlockNumbers->Array.length
43
+ switch trackingCheckpointsCount {
44
+ | 1 => safeCheckpointTracking.checkpointIds->Belt.Array.getUnsafe(0)
45
+ | _ => {
46
+ let result = ref(None)
47
+ let idx = ref(1)
48
+
49
+ while idx.contents < trackingCheckpointsCount && result.contents === None {
50
+ if (
51
+ safeCheckpointTracking.checkpointBlockNumbers->Belt.Array.getUnsafe(idx.contents) >
52
+ safeBlockNumber
53
+ ) {
54
+ result :=
55
+ Some(safeCheckpointTracking.checkpointIds->Belt.Array.getUnsafe(idx.contents - 1))
56
+ }
57
+ idx := idx.contents + 1
58
+ }
59
+
60
+ switch result.contents {
61
+ | Some(checkpointId) => checkpointId
62
+ | None =>
63
+ safeCheckpointTracking.checkpointIds->Belt.Array.getUnsafe(trackingCheckpointsCount - 1)
64
+ }
65
+ }
66
+ }
67
+ }
68
+ }
69
+
70
+ let updateOnNewBatch = (
71
+ safeCheckpointTracking: t,
72
+ ~sourceBlockNumber: int,
73
+ ~chainId: int,
74
+ ~batchCheckpointIds: array<int>,
75
+ ~batchCheckpointBlockNumbers: array<int>,
76
+ ~batchCheckpointChainIds: array<int>,
77
+ ) => {
78
+ let safeCheckpointId = getSafeCheckpointId(safeCheckpointTracking, ~sourceBlockNumber)
79
+
80
+ let mutCheckpointIds = []
81
+ let mutCheckpointBlockNumbers = []
82
+
83
+ // Copy + Clean up old checkpoints
84
+ for idx in 0 to safeCheckpointTracking.checkpointIds->Array.length - 1 {
85
+ let checkpointId = safeCheckpointTracking.checkpointIds->Belt.Array.getUnsafe(idx)
86
+ if checkpointId >= safeCheckpointId {
87
+ mutCheckpointIds->Js.Array2.push(checkpointId)->ignore
88
+ mutCheckpointBlockNumbers
89
+ ->Js.Array2.push(safeCheckpointTracking.checkpointBlockNumbers->Belt.Array.getUnsafe(idx))
90
+ ->ignore
91
+ }
92
+ }
93
+
94
+ // Append new checkpoints
95
+ for idx in 0 to batchCheckpointIds->Array.length - 1 {
96
+ if batchCheckpointChainIds->Belt.Array.getUnsafe(idx) === chainId {
97
+ mutCheckpointIds->Js.Array2.push(batchCheckpointIds->Belt.Array.getUnsafe(idx))->ignore
98
+ mutCheckpointBlockNumbers
99
+ ->Js.Array2.push(batchCheckpointBlockNumbers->Belt.Array.getUnsafe(idx))
100
+ ->ignore
101
+ }
102
+ }
103
+
104
+ {
105
+ checkpointIds: mutCheckpointIds,
106
+ checkpointBlockNumbers: mutCheckpointBlockNumbers,
107
+ maxReorgDepth: safeCheckpointTracking.maxReorgDepth,
108
+ }
109
+ }
110
+
111
+ let rollback = (safeCheckpointTracking: t, ~targetBlockNumber: int) => {
112
+ let mutCheckpointIds = []
113
+ let mutCheckpointBlockNumbers = []
114
+
115
+ for idx in 0 to safeCheckpointTracking.checkpointIds->Array.length - 1 {
116
+ let blockNumber = safeCheckpointTracking.checkpointBlockNumbers->Belt.Array.getUnsafe(idx)
117
+ if blockNumber <= targetBlockNumber {
118
+ mutCheckpointIds
119
+ ->Js.Array2.push(safeCheckpointTracking.checkpointIds->Belt.Array.getUnsafe(idx))
120
+ ->ignore
121
+ mutCheckpointBlockNumbers
122
+ ->Js.Array2.push(safeCheckpointTracking.checkpointBlockNumbers->Belt.Array.getUnsafe(idx))
123
+ ->ignore
124
+ }
125
+ }
126
+
127
+ {
128
+ checkpointIds: mutCheckpointIds,
129
+ checkpointBlockNumbers: mutCheckpointBlockNumbers,
130
+ maxReorgDepth: safeCheckpointTracking.maxReorgDepth,
131
+ }
132
+ }
@@ -0,0 +1,95 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+ 'use strict';
3
+
4
+
5
+ function make(maxReorgDepth, shouldRollbackOnReorg, chainReorgCheckpoints) {
6
+ if (!(maxReorgDepth > 0 && shouldRollbackOnReorg)) {
7
+ return ;
8
+ }
9
+ var checkpointIds = new Array(chainReorgCheckpoints.length);
10
+ var checkpointBlockNumbers = new Array(chainReorgCheckpoints.length);
11
+ chainReorgCheckpoints.forEach(function (checkpoint, idx) {
12
+ checkpointIds[idx] = checkpoint.id;
13
+ checkpointBlockNumbers[idx] = checkpoint.block_number;
14
+ });
15
+ return {
16
+ checkpointIds: checkpointIds,
17
+ checkpointBlockNumbers: checkpointBlockNumbers,
18
+ maxReorgDepth: maxReorgDepth
19
+ };
20
+ }
21
+
22
+ function getSafeCheckpointId(safeCheckpointTracking, sourceBlockNumber) {
23
+ var safeBlockNumber = sourceBlockNumber - safeCheckpointTracking.maxReorgDepth | 0;
24
+ if (safeCheckpointTracking.checkpointBlockNumbers[0] > safeBlockNumber) {
25
+ return 0;
26
+ }
27
+ var trackingCheckpointsCount = safeCheckpointTracking.checkpointBlockNumbers.length;
28
+ if (trackingCheckpointsCount === 1) {
29
+ return safeCheckpointTracking.checkpointIds[0];
30
+ }
31
+ var result;
32
+ var idx = 1;
33
+ while(idx < trackingCheckpointsCount && result === undefined) {
34
+ if (safeCheckpointTracking.checkpointBlockNumbers[idx] > safeBlockNumber) {
35
+ result = safeCheckpointTracking.checkpointIds[idx - 1 | 0];
36
+ }
37
+ idx = idx + 1 | 0;
38
+ };
39
+ var checkpointId = result;
40
+ if (checkpointId !== undefined) {
41
+ return checkpointId;
42
+ } else {
43
+ return safeCheckpointTracking.checkpointIds[trackingCheckpointsCount - 1 | 0];
44
+ }
45
+ }
46
+
47
+ function updateOnNewBatch(safeCheckpointTracking, sourceBlockNumber, chainId, batchCheckpointIds, batchCheckpointBlockNumbers, batchCheckpointChainIds) {
48
+ var safeCheckpointId = getSafeCheckpointId(safeCheckpointTracking, sourceBlockNumber);
49
+ var mutCheckpointIds = [];
50
+ var mutCheckpointBlockNumbers = [];
51
+ for(var idx = 0 ,idx_finish = safeCheckpointTracking.checkpointIds.length; idx < idx_finish; ++idx){
52
+ var checkpointId = safeCheckpointTracking.checkpointIds[idx];
53
+ if (checkpointId >= safeCheckpointId) {
54
+ mutCheckpointIds.push(checkpointId);
55
+ mutCheckpointBlockNumbers.push(safeCheckpointTracking.checkpointBlockNumbers[idx]);
56
+ }
57
+
58
+ }
59
+ for(var idx$1 = 0 ,idx_finish$1 = batchCheckpointIds.length; idx$1 < idx_finish$1; ++idx$1){
60
+ if (batchCheckpointChainIds[idx$1] === chainId) {
61
+ mutCheckpointIds.push(batchCheckpointIds[idx$1]);
62
+ mutCheckpointBlockNumbers.push(batchCheckpointBlockNumbers[idx$1]);
63
+ }
64
+
65
+ }
66
+ return {
67
+ checkpointIds: mutCheckpointIds,
68
+ checkpointBlockNumbers: mutCheckpointBlockNumbers,
69
+ maxReorgDepth: safeCheckpointTracking.maxReorgDepth
70
+ };
71
+ }
72
+
73
+ function rollback(safeCheckpointTracking, targetBlockNumber) {
74
+ var mutCheckpointIds = [];
75
+ var mutCheckpointBlockNumbers = [];
76
+ for(var idx = 0 ,idx_finish = safeCheckpointTracking.checkpointIds.length; idx < idx_finish; ++idx){
77
+ var blockNumber = safeCheckpointTracking.checkpointBlockNumbers[idx];
78
+ if (blockNumber <= targetBlockNumber) {
79
+ mutCheckpointIds.push(safeCheckpointTracking.checkpointIds[idx]);
80
+ mutCheckpointBlockNumbers.push(safeCheckpointTracking.checkpointBlockNumbers[idx]);
81
+ }
82
+
83
+ }
84
+ return {
85
+ checkpointIds: mutCheckpointIds,
86
+ checkpointBlockNumbers: mutCheckpointBlockNumbers,
87
+ maxReorgDepth: safeCheckpointTracking.maxReorgDepth
88
+ };
89
+ }
90
+
91
+ exports.make = make;
92
+ exports.getSafeCheckpointId = getSafeCheckpointId;
93
+ exports.updateOnNewBatch = updateOnNewBatch;
94
+ exports.rollback = rollback;
95
+ /* No side effect */
package/src/Utils.res CHANGED
@@ -97,30 +97,66 @@ module Dict = {
97
97
  @val
98
98
  external mergeInPlace: (dict<'a>, dict<'a>) => dict<'a> = "Object.assign"
99
99
 
100
- let map = (dict, fn) => {
101
- let newDict = Js.Dict.empty()
102
- let keys = dict->Js.Dict.keys
103
- for idx in 0 to keys->Js.Array2.length - 1 {
104
- let key = keys->Js.Array2.unsafe_get(idx)
105
- newDict->Js.Dict.set(key, fn(dict->Js.Dict.unsafeGet(key)))
100
+ // Use %raw to support for..in which is a ~10% faster than .forEach
101
+ let mapValues: (dict<'a>, 'a => 'b) => dict<'b> = %raw(`(dict, f) => {
102
+ var target = {}, i;
103
+ for (i in dict) {
104
+ target[i] = f(dict[i]);
106
105
  }
107
- newDict
108
- }
106
+ return target;
107
+ }`)
109
108
 
110
- let forEach = (dict, fn) => {
111
- let keys = dict->Js.Dict.keys
112
- for idx in 0 to keys->Js.Array2.length - 1 {
113
- fn(dict->Js.Dict.unsafeGet(keys->Js.Array2.unsafe_get(idx)))
109
+ // Use %raw to support for..in which is a ~10% faster than .forEach
110
+ let filterMapValues: (dict<'a>, 'a => option<'b>) => dict<'b> = %raw(`(dict, f) => {
111
+ var target = {}, i, v;
112
+ for (i in dict) {
113
+ v = f(dict[i]);
114
+ if (v !== undefined) {
115
+ target[i] = v;
116
+ }
114
117
  }
115
- }
118
+ return target;
119
+ }`)
116
120
 
117
- let forEachWithKey = (dict, fn) => {
118
- let keys = dict->Js.Dict.keys
119
- for idx in 0 to keys->Js.Array2.length - 1 {
120
- let key = keys->Js.Array2.unsafe_get(idx)
121
- fn(key, dict->Js.Dict.unsafeGet(key))
121
+ // Use %raw to support for..in which is a ~10% faster than .forEach
122
+ let mapValuesToArray: (dict<'a>, 'a => 'b) => array<'b> = %raw(`(dict, f) => {
123
+ var target = [], i;
124
+ for (i in dict) {
125
+ target.push(f(dict[i]));
122
126
  }
123
- }
127
+ return target;
128
+ }`)
129
+
130
+ // Use %raw to support for..in which is a ~10% faster than .forEach
131
+ let forEach: (dict<'a>, 'a => unit) => unit = %raw(`(dict, f) => {
132
+ for (var i in dict) {
133
+ f(dict[i]);
134
+ }
135
+ }`)
136
+
137
+ // Use %raw to support for..in which is a ~10% faster than .forEach
138
+ let forEachWithKey: (dict<'a>, ('a, string) => unit) => unit = %raw(`(dict, f) => {
139
+ for (var i in dict) {
140
+ f(dict[i], i);
141
+ }
142
+ }`)
143
+
144
+ // Use %raw to support for..in which is a ~10% faster than Object.keys
145
+ let size: dict<'a> => int = %raw(`(dict) => {
146
+ var size = 0, i;
147
+ for (i in dict) {
148
+ size++;
149
+ }
150
+ return size;
151
+ }`)
152
+
153
+ // Use %raw to support for..in which is a 2x faster than Object.keys
154
+ let isEmpty: dict<'a> => bool = %raw(`(dict) => {
155
+ for (var _ in dict) {
156
+ return false
157
+ }
158
+ return true
159
+ }`)
124
160
 
125
161
  let deleteInPlace: (dict<'a>, string) => unit = %raw(`(dict, key) => {
126
162
  delete dict[key];
@@ -135,8 +171,6 @@ module Dict = {
135
171
 
136
172
  let shallowCopy: dict<'a> => dict<'a> = %raw(`(dict) => ({...dict})`)
137
173
 
138
- let size = dict => dict->Js.Dict.keys->Js.Array2.length
139
-
140
174
  @set_index
141
175
  external setByInt: (dict<'a>, int, 'a) => unit = ""
142
176
 
@@ -155,6 +189,15 @@ module Math = {
155
189
  }
156
190
  }
157
191
 
192
+ // This is a microoptimization to avoid int32 safeguards
193
+ module UnsafeIntOperators = {
194
+ external \"*": (int, int) => int = "%mulfloat"
195
+
196
+ external \"+": (int, int) => int = "%addfloat"
197
+
198
+ external \"-": (int, int) => int = "%subfloat"
199
+ }
200
+
158
201
  module Array = {
159
202
  @send
160
203
  external forEachAsync: (array<'a>, 'a => promise<unit>) => unit = "forEach"
package/src/Utils.res.js CHANGED
@@ -93,30 +93,59 @@ function pushMany(dict, key, values) {
93
93
 
94
94
  var merge = ((dictA, dictB) => ({...dictA, ...dictB}));
95
95
 
96
- function map(dict, fn) {
97
- var newDict = {};
98
- var keys = Object.keys(dict);
99
- for(var idx = 0 ,idx_finish = keys.length; idx < idx_finish; ++idx){
100
- var key = keys[idx];
101
- newDict[key] = fn(dict[key]);
102
- }
103
- return newDict;
104
- }
96
+ var mapValues = ((dict, f) => {
97
+ var target = {}, i;
98
+ for (i in dict) {
99
+ target[i] = f(dict[i]);
100
+ }
101
+ return target;
102
+ });
105
103
 
106
- function forEach(dict, fn) {
107
- var keys = Object.keys(dict);
108
- for(var idx = 0 ,idx_finish = keys.length; idx < idx_finish; ++idx){
109
- fn(dict[keys[idx]]);
110
- }
111
- }
104
+ var filterMapValues = ((dict, f) => {
105
+ var target = {}, i, v;
106
+ for (i in dict) {
107
+ v = f(dict[i]);
108
+ if (v !== undefined) {
109
+ target[i] = v;
110
+ }
111
+ }
112
+ return target;
113
+ });
112
114
 
113
- function forEachWithKey(dict, fn) {
114
- var keys = Object.keys(dict);
115
- for(var idx = 0 ,idx_finish = keys.length; idx < idx_finish; ++idx){
116
- var key = keys[idx];
117
- fn(key, dict[key]);
118
- }
119
- }
115
+ var mapValuesToArray = ((dict, f) => {
116
+ var target = [], i;
117
+ for (i in dict) {
118
+ target.push(f(dict[i]));
119
+ }
120
+ return target;
121
+ });
122
+
123
+ var forEach = ((dict, f) => {
124
+ for (var i in dict) {
125
+ f(dict[i]);
126
+ }
127
+ });
128
+
129
+ var forEachWithKey = ((dict, f) => {
130
+ for (var i in dict) {
131
+ f(dict[i], i);
132
+ }
133
+ });
134
+
135
+ var size = ((dict) => {
136
+ var size = 0, i;
137
+ for (i in dict) {
138
+ size++;
139
+ }
140
+ return size;
141
+ });
142
+
143
+ var isEmpty = ((dict) => {
144
+ for (var _ in dict) {
145
+ return false
146
+ }
147
+ return true
148
+ });
120
149
 
121
150
  var deleteInPlace = ((dict, key) => {
122
151
  delete dict[key];
@@ -126,10 +155,6 @@ var updateImmutable = ((dict, key, value) => ({...dict, [key]: value}));
126
155
 
127
156
  var shallowCopy = ((dict) => ({...dict}));
128
157
 
129
- function size(dict) {
130
- return Object.keys(dict).length;
131
- }
132
-
133
158
  var incrementByInt = ((dict, key) => {
134
159
  dict[key]++
135
160
  });
@@ -139,13 +164,16 @@ var Dict = {
139
164
  push: push,
140
165
  pushMany: pushMany,
141
166
  merge: merge,
142
- map: map,
167
+ mapValues: mapValues,
168
+ filterMapValues: filterMapValues,
169
+ mapValuesToArray: mapValuesToArray,
143
170
  forEach: forEach,
144
171
  forEachWithKey: forEachWithKey,
172
+ size: size,
173
+ isEmpty: isEmpty,
145
174
  deleteInPlace: deleteInPlace,
146
175
  updateImmutable: updateImmutable,
147
176
  shallowCopy: shallowCopy,
148
- size: size,
149
177
  incrementByInt: incrementByInt
150
178
  };
151
179
 
@@ -169,6 +197,8 @@ var $$Math = {
169
197
  minOptInt: minOptInt
170
198
  };
171
199
 
200
+ var UnsafeIntOperators = {};
201
+
172
202
  function mergeSorted(f, xs, ys) {
173
203
  if (xs.length === 0) {
174
204
  return ys;
@@ -251,7 +281,7 @@ function includes(arr, val) {
251
281
  })));
252
282
  }
253
283
 
254
- function isEmpty(arr) {
284
+ function isEmpty$1(arr) {
255
285
  return arr.length === 0;
256
286
  }
257
287
 
@@ -320,7 +350,7 @@ var $$Array$1 = {
320
350
  setIndexImmutable: setIndexImmutable,
321
351
  transposeResults: transposeResults,
322
352
  includes: includes,
323
- isEmpty: isEmpty,
353
+ isEmpty: isEmpty$1,
324
354
  notEmpty: notEmpty,
325
355
  awaitEach: awaitEach,
326
356
  removeAtIndex: removeAtIndex,
@@ -557,6 +587,7 @@ exports.$$Option = $$Option;
557
587
  exports.Tuple = Tuple;
558
588
  exports.Dict = Dict;
559
589
  exports.$$Math = $$Math;
590
+ exports.UnsafeIntOperators = UnsafeIntOperators;
560
591
  exports.$$Array = $$Array$1;
561
592
  exports.$$String = $$String;
562
593
  exports.Result = Result;