envio 2.32.1 → 3.0.0-alpha-main-clickhouse-sink
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/index.d.ts +1 -0
- package/package.json +6 -5
- package/src/Batch.res +4 -4
- package/src/Change.res +9 -0
- package/src/Change.res.js +2 -0
- package/src/Config.res +5 -5
- package/src/Config.res.js +3 -1
- package/src/Envio.gen.ts +3 -3
- package/src/Envio.res +14 -3
- package/src/EventRegister.res +3 -11
- package/src/EventRegister.res.js +4 -8
- package/src/EventRegister.resi +1 -1
- package/src/InMemoryStore.gen.ts +6 -0
- package/src/InMemoryStore.res +149 -0
- package/src/InMemoryStore.res.js +161 -0
- package/src/InMemoryTable.res +50 -35
- package/src/InMemoryTable.res.js +52 -84
- package/src/Internal.gen.ts +0 -2
- package/src/Internal.res +20 -38
- package/src/Internal.res.js +2 -16
- package/src/LoadManager.res +23 -16
- package/src/LoadManager.res.js +17 -15
- package/src/Persistence.res +190 -38
- package/src/Persistence.res.js +92 -39
- package/src/PgStorage.res +700 -14
- package/src/PgStorage.res.js +431 -19
- package/src/Platform.res +141 -0
- package/src/Platform.res.js +170 -0
- package/src/Prometheus.res +41 -0
- package/src/Prometheus.res.js +45 -0
- package/src/SafeCheckpointTracking.res +5 -4
- package/src/Sink.res +47 -0
- package/src/Sink.res.js +36 -0
- package/src/Utils.res +2 -0
- package/src/Utils.res.js +3 -0
- package/src/bindings/ClickHouse.res +387 -0
- package/src/bindings/ClickHouse.res.js +274 -0
- package/src/bindings/Postgres.res +15 -0
- package/src/bindings/Promise.res +3 -0
- package/src/db/EntityHistory.res +33 -156
- package/src/db/EntityHistory.res.js +40 -115
- package/src/db/InternalTable.res +56 -55
- package/src/db/InternalTable.res.js +49 -52
- package/src/db/Table.res +86 -22
- package/src/db/Table.res.js +77 -10
package/src/Persistence.res
CHANGED
|
@@ -29,13 +29,24 @@ type initialState = {
|
|
|
29
29
|
cleanRun: bool,
|
|
30
30
|
cache: dict<effectCacheRecord>,
|
|
31
31
|
chains: array<initialChainState>,
|
|
32
|
-
checkpointId:
|
|
32
|
+
checkpointId: Internal.checkpointId,
|
|
33
33
|
// Needed to keep reorg detection logic between restarts
|
|
34
34
|
reorgCheckpoints: array<Internal.reorgCheckpoint>,
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
type operator = [#">" | #"=" | #"<"]
|
|
38
38
|
|
|
39
|
+
type updatedEffectCache = {
|
|
40
|
+
effect: Internal.effect,
|
|
41
|
+
items: array<Internal.effectCacheItem>,
|
|
42
|
+
shouldInitialize: bool,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
type updatedEntity = {
|
|
46
|
+
entityConfig: Internal.entityConfig,
|
|
47
|
+
updates: array<Internal.inMemoryStoreEntityUpdate<Internal.entity>>,
|
|
48
|
+
}
|
|
49
|
+
|
|
39
50
|
type storage = {
|
|
40
51
|
// Should return true if we already have persisted data
|
|
41
52
|
// and we can skip initialization
|
|
@@ -45,7 +56,7 @@ type storage = {
|
|
|
45
56
|
initialize: (
|
|
46
57
|
~chainConfigs: array<Config.chain>=?,
|
|
47
58
|
~entities: array<Internal.entityConfig>=?,
|
|
48
|
-
~enums: array<
|
|
59
|
+
~enums: array<Table.enumConfig<Table.enum>>=?,
|
|
49
60
|
) => promise<initialState>,
|
|
50
61
|
resumeInitialState: unit => promise<initialState>,
|
|
51
62
|
@raises("StorageError")
|
|
@@ -77,10 +88,53 @@ type storage = {
|
|
|
77
88
|
) => promise<unit>,
|
|
78
89
|
// This is to download cache from the database to .envio/cache
|
|
79
90
|
dumpEffectCache: unit => promise<unit>,
|
|
91
|
+
// Execute raw SQL query
|
|
92
|
+
executeUnsafe: string => promise<unknown>,
|
|
93
|
+
// Check if entity history has rows
|
|
94
|
+
hasEntityHistoryRows: unit => promise<bool>,
|
|
95
|
+
// Update chain metadata
|
|
96
|
+
setChainMeta: dict<InternalTable.Chains.metaFields> => promise<unknown>,
|
|
97
|
+
// Prune old checkpoints
|
|
98
|
+
pruneStaleCheckpoints: (~safeCheckpointId: Internal.checkpointId) => promise<unit>,
|
|
99
|
+
// Prune stale entity history
|
|
100
|
+
pruneStaleEntityHistory: (
|
|
101
|
+
~entityName: string,
|
|
102
|
+
~entityIndex: int,
|
|
103
|
+
~safeCheckpointId: Internal.checkpointId,
|
|
104
|
+
) => promise<unit>,
|
|
105
|
+
// Get rollback target checkpoint
|
|
106
|
+
getRollbackTargetCheckpoint: (
|
|
107
|
+
~reorgChainId: int,
|
|
108
|
+
~lastKnownValidBlockNumber: int,
|
|
109
|
+
) => promise<array<{"id": Internal.checkpointId}>>,
|
|
110
|
+
// Get rollback progress diff
|
|
111
|
+
getRollbackProgressDiff: (
|
|
112
|
+
~rollbackTargetCheckpointId: Internal.checkpointId,
|
|
113
|
+
) => promise<
|
|
114
|
+
array<{
|
|
115
|
+
"chain_id": int,
|
|
116
|
+
"events_processed_diff": string,
|
|
117
|
+
"new_progress_block_number": int,
|
|
118
|
+
}>,
|
|
119
|
+
>,
|
|
120
|
+
// Get rollback data for entity
|
|
121
|
+
getRollbackData: (
|
|
122
|
+
~entityConfig: Internal.entityConfig,
|
|
123
|
+
~rollbackTargetCheckpointId: Internal.checkpointId,
|
|
124
|
+
) => promise<(array<{"id": string}>, array<unknown>)>,
|
|
125
|
+
// Write batch to storage
|
|
126
|
+
writeBatch: (
|
|
127
|
+
~batch: Batch.t,
|
|
128
|
+
~rawEvents: array<InternalTable.RawEvents.t>,
|
|
129
|
+
~rollbackTargetCheckpointId: option<Internal.checkpointId>,
|
|
130
|
+
~isInReorgThreshold: bool,
|
|
131
|
+
~config: Config.t,
|
|
132
|
+
~allEntities: array<Internal.entityConfig>,
|
|
133
|
+
~updatedEffectsCache: array<updatedEffectCache>,
|
|
134
|
+
~updatedEntities: array<updatedEntity>,
|
|
135
|
+
) => promise<unit>,
|
|
80
136
|
}
|
|
81
137
|
|
|
82
|
-
exception StorageError({message: string, reason: exn})
|
|
83
|
-
|
|
84
138
|
type storageStatus =
|
|
85
139
|
| Unknown
|
|
86
140
|
| Initializing(promise<unit>)
|
|
@@ -89,38 +143,28 @@ type storageStatus =
|
|
|
89
143
|
type t = {
|
|
90
144
|
userEntities: array<Internal.entityConfig>,
|
|
91
145
|
allEntities: array<Internal.entityConfig>,
|
|
92
|
-
allEnums: array<
|
|
146
|
+
allEnums: array<Table.enumConfig<Table.enum>>,
|
|
93
147
|
mutable storageStatus: storageStatus,
|
|
94
148
|
mutable storage: storage,
|
|
95
|
-
// FIXME: This is temporary to move it library
|
|
96
|
-
// Should be a part of the storage interface and db agnostic
|
|
97
|
-
mutable sql: Postgres.sql,
|
|
98
149
|
}
|
|
99
150
|
|
|
100
|
-
|
|
101
|
-
name: EntityHistory.RowAction.name,
|
|
102
|
-
variants: EntityHistory.RowAction.variants,
|
|
103
|
-
schema: EntityHistory.RowAction.schema,
|
|
104
|
-
default: SET,
|
|
105
|
-
}
|
|
151
|
+
exception StorageError({message: string, reason: exn})
|
|
106
152
|
|
|
107
153
|
let make = (
|
|
108
154
|
~userEntities,
|
|
109
155
|
// TODO: Should only pass userEnums and create internal config in runtime
|
|
110
156
|
~allEnums,
|
|
111
157
|
~storage,
|
|
112
|
-
~sql,
|
|
113
158
|
) => {
|
|
114
159
|
let allEntities = userEntities->Js.Array2.concat([InternalTable.DynamicContractRegistry.config])
|
|
115
160
|
let allEnums =
|
|
116
|
-
allEnums->Js.Array2.concat([
|
|
161
|
+
allEnums->Js.Array2.concat([EntityHistory.RowAction.config->Table.fromGenericEnumConfig])
|
|
117
162
|
{
|
|
118
163
|
userEntities,
|
|
119
164
|
allEntities,
|
|
120
165
|
allEnums,
|
|
121
166
|
storageStatus: Unknown,
|
|
122
167
|
storage,
|
|
123
|
-
sql,
|
|
124
168
|
}
|
|
125
169
|
}
|
|
126
170
|
|
|
@@ -197,32 +241,140 @@ let getInitializedState = persistence => {
|
|
|
197
241
|
}
|
|
198
242
|
}
|
|
199
243
|
|
|
200
|
-
let
|
|
244
|
+
let writeBatch = (
|
|
201
245
|
persistence,
|
|
202
|
-
~
|
|
203
|
-
~
|
|
204
|
-
~
|
|
205
|
-
|
|
246
|
+
~batch,
|
|
247
|
+
~config,
|
|
248
|
+
~inMemoryStore: InMemoryStore.t,
|
|
249
|
+
~isInReorgThreshold,
|
|
250
|
+
) =>
|
|
206
251
|
switch persistence.storageStatus {
|
|
207
252
|
| Unknown
|
|
208
253
|
| Initializing(_) =>
|
|
209
254
|
Js.Exn.raiseError(`Failed to access the indexer storage. The Persistence layer is not initialized.`)
|
|
210
|
-
| Ready({cache}) =>
|
|
211
|
-
|
|
212
|
-
let
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
}
|
|
255
|
+
| Ready({cache}) =>
|
|
256
|
+
let updatedEntities = persistence.allEntities->Belt.Array.keepMapU(entityConfig => {
|
|
257
|
+
let updates =
|
|
258
|
+
inMemoryStore
|
|
259
|
+
->InMemoryStore.getInMemTable(~entityConfig)
|
|
260
|
+
->InMemoryTable.Entity.updates
|
|
261
|
+
if updates->Utils.Array.isEmpty {
|
|
262
|
+
None
|
|
263
|
+
} else {
|
|
264
|
+
Some({entityConfig, updates})
|
|
220
265
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
266
|
+
})
|
|
267
|
+
persistence.storage.writeBatch(
|
|
268
|
+
~batch,
|
|
269
|
+
~rawEvents=inMemoryStore.rawEvents->InMemoryTable.values,
|
|
270
|
+
~rollbackTargetCheckpointId=inMemoryStore.rollbackTargetCheckpointId,
|
|
271
|
+
~isInReorgThreshold,
|
|
272
|
+
~config,
|
|
273
|
+
~allEntities=persistence.allEntities,
|
|
274
|
+
~updatedEntities,
|
|
275
|
+
~updatedEffectsCache={
|
|
276
|
+
inMemoryStore.effects
|
|
277
|
+
->Js.Dict.keys
|
|
278
|
+
->Belt.Array.keepMapU(effectName => {
|
|
279
|
+
let inMemTable = inMemoryStore.effects->Js.Dict.unsafeGet(effectName)
|
|
280
|
+
let {idsToStore, dict, effect, invalidationsCount} = inMemTable
|
|
281
|
+
switch idsToStore {
|
|
282
|
+
| [] => None
|
|
283
|
+
| ids => {
|
|
284
|
+
let items = Belt.Array.makeUninitializedUnsafe(ids->Belt.Array.length)
|
|
285
|
+
ids->Belt.Array.forEachWithIndex((index, id) => {
|
|
286
|
+
items->Js.Array2.unsafe_set(
|
|
287
|
+
index,
|
|
288
|
+
(
|
|
289
|
+
{
|
|
290
|
+
id,
|
|
291
|
+
output: dict->Js.Dict.unsafeGet(id),
|
|
292
|
+
}: Internal.effectCacheItem
|
|
293
|
+
),
|
|
294
|
+
)
|
|
295
|
+
})
|
|
296
|
+
Some({
|
|
297
|
+
let effectName = effect.name
|
|
298
|
+
let effectCacheRecord = switch cache->Utils.Dict.dangerouslyGetNonOption(
|
|
299
|
+
effectName,
|
|
300
|
+
) {
|
|
301
|
+
| Some(c) => c
|
|
302
|
+
| None => {
|
|
303
|
+
let c = {effectName, count: 0}
|
|
304
|
+
cache->Js.Dict.set(effectName, c)
|
|
305
|
+
c
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
let shouldInitialize = effectCacheRecord.count === 0
|
|
309
|
+
effectCacheRecord.count =
|
|
310
|
+
effectCacheRecord.count + items->Js.Array2.length - invalidationsCount
|
|
311
|
+
Prometheus.EffectCacheCount.set(~count=effectCacheRecord.count, ~effectName)
|
|
312
|
+
{effect, items, shouldInitialize}
|
|
313
|
+
})
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
})
|
|
317
|
+
},
|
|
318
|
+
)
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
let prepareRollbackDiff = async (
|
|
322
|
+
persistence: t,
|
|
323
|
+
~rollbackTargetCheckpointId,
|
|
324
|
+
~rollbackDiffCheckpointId,
|
|
325
|
+
) => {
|
|
326
|
+
let inMemStore = InMemoryStore.make(
|
|
327
|
+
~entities=persistence.allEntities,
|
|
328
|
+
~rollbackTargetCheckpointId,
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
let deletedEntities = Js.Dict.empty()
|
|
332
|
+
let setEntities = Js.Dict.empty()
|
|
333
|
+
|
|
334
|
+
let _ =
|
|
335
|
+
await persistence.allEntities
|
|
336
|
+
->Belt.Array.map(async entityConfig => {
|
|
337
|
+
let entityTable = inMemStore->InMemoryStore.getInMemTable(~entityConfig)
|
|
338
|
+
|
|
339
|
+
let (removedIdsResult, restoredEntitiesResult) = await persistence.storage.getRollbackData(
|
|
340
|
+
~entityConfig,
|
|
341
|
+
~rollbackTargetCheckpointId,
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
// Process removed IDs
|
|
345
|
+
removedIdsResult->Js.Array2.forEach(data => {
|
|
346
|
+
deletedEntities->Utils.Dict.push(entityConfig.name, data["id"])
|
|
347
|
+
entityTable->InMemoryTable.Entity.set(
|
|
348
|
+
Delete({
|
|
349
|
+
entityId: data["id"],
|
|
350
|
+
checkpointId: rollbackDiffCheckpointId,
|
|
351
|
+
}),
|
|
352
|
+
~shouldSaveHistory=false,
|
|
353
|
+
~containsRollbackDiffChange=true,
|
|
354
|
+
)
|
|
355
|
+
})
|
|
356
|
+
|
|
357
|
+
let restoredEntities = restoredEntitiesResult->S.parseOrThrow(entityConfig.rowsSchema)
|
|
358
|
+
|
|
359
|
+
// Process restored entities
|
|
360
|
+
restoredEntities->Belt.Array.forEach((entity: Internal.entity) => {
|
|
361
|
+
setEntities->Utils.Dict.push(entityConfig.name, entity.id)
|
|
362
|
+
entityTable->InMemoryTable.Entity.set(
|
|
363
|
+
Set({
|
|
364
|
+
entityId: entity.id,
|
|
365
|
+
checkpointId: rollbackDiffCheckpointId,
|
|
366
|
+
entity,
|
|
367
|
+
}),
|
|
368
|
+
~shouldSaveHistory=false,
|
|
369
|
+
~containsRollbackDiffChange=true,
|
|
370
|
+
)
|
|
371
|
+
})
|
|
372
|
+
})
|
|
373
|
+
->Promise.all
|
|
374
|
+
|
|
375
|
+
{
|
|
376
|
+
"inMemStore": inMemStore,
|
|
377
|
+
"deletedEntities": deletedEntities,
|
|
378
|
+
"setEntities": setEntities,
|
|
227
379
|
}
|
|
228
380
|
}
|
package/src/Persistence.res.js
CHANGED
|
@@ -1,40 +1,31 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
+
var Utils = require("./Utils.res.js");
|
|
4
5
|
var Js_exn = require("rescript/lib/js/js_exn.js");
|
|
5
6
|
var Logging = require("./Logging.res.js");
|
|
7
|
+
var Belt_Array = require("rescript/lib/js/belt_Array.js");
|
|
6
8
|
var Prometheus = require("./Prometheus.res.js");
|
|
7
9
|
var EntityHistory = require("./db/EntityHistory.res.js");
|
|
8
10
|
var ErrorHandling = require("./ErrorHandling.res.js");
|
|
11
|
+
var InMemoryStore = require("./InMemoryStore.res.js");
|
|
12
|
+
var InMemoryTable = require("./InMemoryTable.res.js");
|
|
9
13
|
var InternalTable = require("./db/InternalTable.res.js");
|
|
10
14
|
var Caml_exceptions = require("rescript/lib/js/caml_exceptions.js");
|
|
15
|
+
var S$RescriptSchema = require("rescript-schema/src/S.res.js");
|
|
11
16
|
var Caml_js_exceptions = require("rescript/lib/js/caml_js_exceptions.js");
|
|
12
17
|
|
|
13
18
|
var StorageError = /* @__PURE__ */Caml_exceptions.create("Persistence.StorageError");
|
|
14
19
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
var entityHistoryActionEnumConfig_variants = EntityHistory.RowAction.variants;
|
|
18
|
-
|
|
19
|
-
var entityHistoryActionEnumConfig_schema = EntityHistory.RowAction.schema;
|
|
20
|
-
|
|
21
|
-
var entityHistoryActionEnumConfig = {
|
|
22
|
-
name: entityHistoryActionEnumConfig_name,
|
|
23
|
-
variants: entityHistoryActionEnumConfig_variants,
|
|
24
|
-
schema: entityHistoryActionEnumConfig_schema,
|
|
25
|
-
default: "SET"
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
function make(userEntities, allEnums, storage, sql) {
|
|
20
|
+
function make(userEntities, allEnums, storage) {
|
|
29
21
|
var allEntities = userEntities.concat([InternalTable.DynamicContractRegistry.config]);
|
|
30
|
-
var allEnums$1 = allEnums.concat([
|
|
22
|
+
var allEnums$1 = allEnums.concat([EntityHistory.RowAction.config]);
|
|
31
23
|
return {
|
|
32
24
|
userEntities: userEntities,
|
|
33
25
|
allEntities: allEntities,
|
|
34
26
|
allEnums: allEnums$1,
|
|
35
27
|
storageStatus: "Unknown",
|
|
36
|
-
storage: storage
|
|
37
|
-
sql: sql
|
|
28
|
+
storage: storage
|
|
38
29
|
};
|
|
39
30
|
}
|
|
40
31
|
|
|
@@ -120,7 +111,7 @@ function getInitializedState(persistence) {
|
|
|
120
111
|
}
|
|
121
112
|
}
|
|
122
113
|
|
|
123
|
-
|
|
114
|
+
function writeBatch(persistence, batch, config, inMemoryStore, isInReorgThreshold) {
|
|
124
115
|
var match = persistence.storageStatus;
|
|
125
116
|
if (typeof match !== "object") {
|
|
126
117
|
return Js_exn.raiseError("Failed to access the indexer storage. The Persistence layer is not initialized.");
|
|
@@ -129,31 +120,93 @@ async function setEffectCacheOrThrow(persistence, effect, items, invalidationsCo
|
|
|
129
120
|
return Js_exn.raiseError("Failed to access the indexer storage. The Persistence layer is not initialized.");
|
|
130
121
|
}
|
|
131
122
|
var cache = match._0.cache;
|
|
132
|
-
var
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
123
|
+
var updatedEntities = Belt_Array.keepMapU(persistence.allEntities, (function (entityConfig) {
|
|
124
|
+
var updates = InMemoryTable.Entity.updates(InMemoryStore.getInMemTable(inMemoryStore, entityConfig));
|
|
125
|
+
if (Utils.$$Array.isEmpty(updates)) {
|
|
126
|
+
return ;
|
|
127
|
+
} else {
|
|
128
|
+
return {
|
|
129
|
+
entityConfig: entityConfig,
|
|
130
|
+
updates: updates
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
}));
|
|
134
|
+
return persistence.storage.writeBatch(batch, InMemoryTable.values(inMemoryStore.rawEvents), inMemoryStore.rollbackTargetCheckpointId, isInReorgThreshold, config, persistence.allEntities, Belt_Array.keepMapU(Object.keys(inMemoryStore.effects), (function (effectName) {
|
|
135
|
+
var inMemTable = inMemoryStore.effects[effectName];
|
|
136
|
+
var idsToStore = inMemTable.idsToStore;
|
|
137
|
+
var invalidationsCount = inMemTable.invalidationsCount;
|
|
138
|
+
var effect = inMemTable.effect;
|
|
139
|
+
var dict = inMemTable.dict;
|
|
140
|
+
if (idsToStore.length === 0) {
|
|
141
|
+
return ;
|
|
142
|
+
}
|
|
143
|
+
var items = new Array(idsToStore.length);
|
|
144
|
+
Belt_Array.forEachWithIndex(idsToStore, (function (index, id) {
|
|
145
|
+
items[index] = {
|
|
146
|
+
id: id,
|
|
147
|
+
output: dict[id]
|
|
148
|
+
};
|
|
149
|
+
}));
|
|
150
|
+
var effectName$1 = effect.name;
|
|
151
|
+
var c = cache[effectName$1];
|
|
152
|
+
var effectCacheRecord;
|
|
153
|
+
if (c !== undefined) {
|
|
154
|
+
effectCacheRecord = c;
|
|
155
|
+
} else {
|
|
156
|
+
var c$1 = {
|
|
157
|
+
effectName: effectName$1,
|
|
158
|
+
count: 0
|
|
159
|
+
};
|
|
160
|
+
cache[effectName$1] = c$1;
|
|
161
|
+
effectCacheRecord = c$1;
|
|
162
|
+
}
|
|
163
|
+
var shouldInitialize = effectCacheRecord.count === 0;
|
|
164
|
+
return effectCacheRecord.count = (effectCacheRecord.count + items.length | 0) - invalidationsCount | 0, Prometheus.EffectCacheCount.set(effectCacheRecord.count, effectName$1), {
|
|
165
|
+
effect: effect,
|
|
166
|
+
items: items,
|
|
167
|
+
shouldInitialize: shouldInitialize
|
|
168
|
+
};
|
|
169
|
+
})), updatedEntities);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async function prepareRollbackDiff(persistence, rollbackTargetCheckpointId, rollbackDiffCheckpointId) {
|
|
173
|
+
var inMemStore = InMemoryStore.make(persistence.allEntities, rollbackTargetCheckpointId);
|
|
174
|
+
var deletedEntities = {};
|
|
175
|
+
var setEntities = {};
|
|
176
|
+
await Promise.all(Belt_Array.map(persistence.allEntities, (async function (entityConfig) {
|
|
177
|
+
var entityTable = InMemoryStore.getInMemTable(inMemStore, entityConfig);
|
|
178
|
+
var match = await persistence.storage.getRollbackData(entityConfig, rollbackTargetCheckpointId);
|
|
179
|
+
match[0].forEach(function (data) {
|
|
180
|
+
Utils.Dict.push(deletedEntities, entityConfig.name, data.id);
|
|
181
|
+
InMemoryTable.Entity.set(entityTable, {
|
|
182
|
+
type: "DELETE",
|
|
183
|
+
entityId: data.id,
|
|
184
|
+
checkpointId: rollbackDiffCheckpointId
|
|
185
|
+
}, false, true);
|
|
186
|
+
});
|
|
187
|
+
var restoredEntities = S$RescriptSchema.parseOrThrow(match[1], entityConfig.rowsSchema);
|
|
188
|
+
return Belt_Array.forEach(restoredEntities, (function (entity) {
|
|
189
|
+
Utils.Dict.push(setEntities, entityConfig.name, entity.id);
|
|
190
|
+
InMemoryTable.Entity.set(entityTable, {
|
|
191
|
+
type: "SET",
|
|
192
|
+
entityId: entity.id,
|
|
193
|
+
entity: entity,
|
|
194
|
+
checkpointId: rollbackDiffCheckpointId
|
|
195
|
+
}, false, true);
|
|
196
|
+
}));
|
|
197
|
+
})));
|
|
198
|
+
return {
|
|
199
|
+
inMemStore: inMemStore,
|
|
200
|
+
deletedEntities: deletedEntities,
|
|
201
|
+
setEntities: setEntities
|
|
202
|
+
};
|
|
150
203
|
}
|
|
151
204
|
|
|
152
205
|
exports.StorageError = StorageError;
|
|
153
|
-
exports.entityHistoryActionEnumConfig = entityHistoryActionEnumConfig;
|
|
154
206
|
exports.make = make;
|
|
155
207
|
exports.init = init;
|
|
156
208
|
exports.getInitializedStorageOrThrow = getInitializedStorageOrThrow;
|
|
157
209
|
exports.getInitializedState = getInitializedState;
|
|
158
|
-
exports.
|
|
159
|
-
|
|
210
|
+
exports.writeBatch = writeBatch;
|
|
211
|
+
exports.prepareRollbackDiff = prepareRollbackDiff;
|
|
212
|
+
/* Utils Not a pure module */
|