envio 3.15.0-subgraph → 3.16.0
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/README.md +40 -34
- package/evm.schema.json +3 -3
- package/fuel.schema.json +2 -2
- package/index.d.ts +3 -3
- package/licenses/README.md +1 -1
- package/package.json +9 -10
- package/src/Batch.res.mjs +5 -5
- package/src/BatchProcessing.res +1 -0
- package/src/BatchProcessing.res.mjs +1 -0
- package/src/Bin.res +0 -7
- package/src/Bin.res.mjs +0 -8
- package/src/ChainFetching.res +17 -456
- package/src/ChainFetching.res.mjs +33 -404
- package/src/ChainState.res +48 -83
- package/src/ChainState.res.mjs +83 -115
- package/src/ChainState.resi +0 -26
- package/src/Clock.res +57 -0
- package/src/Clock.res.mjs +72 -0
- package/src/Config.res +7 -16
- package/src/Config.res.mjs +4 -11
- package/src/ContractRegisterContext.res +6 -3
- package/src/ContractRegisterContext.res.mjs +2 -4
- package/src/Core.res +5 -136
- package/src/Core.res.mjs +1 -90
- package/src/CrossChainState.res +2 -8
- package/src/CrossChainState.res.mjs +3 -3
- package/src/Ecosystem.res +4 -7
- package/src/Ecosystem.res.mjs +8 -8
- package/src/EffectState.res +10 -2
- package/src/EffectState.res.mjs +8 -4
- package/src/EffectState.resi +3 -1
- package/src/EntityId.res +2 -7
- package/src/EntityId.res.mjs +1 -8
- package/src/EntityTables.res +4 -1
- package/src/EntityTables.res.mjs +1 -1
- package/src/Env.res +0 -16
- package/src/Env.res.mjs +0 -11
- package/src/EventProcessing.res +1 -38
- package/src/EventProcessing.res.mjs +1 -28
- package/src/FetchState.res +160 -319
- package/src/FetchState.res.mjs +182 -292
- package/src/FinalizeBackfill.res +2 -4
- package/src/FinalizeBackfill.res.mjs +3 -4
- package/src/HandlerLoader.res +15 -39
- package/src/HandlerLoader.res.mjs +8 -27
- package/src/HandlerRegister.res +0 -4
- package/src/HandlerRegister.res.mjs +2 -5
- package/src/HandlerRegister.resi +0 -2
- package/src/InMemoryTable.res +17 -16
- package/src/InMemoryTable.res.mjs +14 -15
- package/src/IndexerState.res +28 -4
- package/src/IndexerState.res.mjs +19 -6
- package/src/IndexerState.resi +4 -0
- package/src/Internal.res +0 -110
- package/src/Internal.res.mjs +1 -115
- package/src/LoadLayer.res +21 -47
- package/src/LoadLayer.res.mjs +47 -72
- package/src/LoadLayer.resi +0 -26
- package/src/Main.res +1 -14
- package/src/Main.res.mjs +3 -4
- package/src/Persistence.res +3 -23
- package/src/Persistence.res.mjs +3 -3
- package/src/Rollback.res +0 -1
- package/src/Rollback.res.mjs +1 -1
- package/src/RunScope.res +0 -3
- package/src/SafeCheckpointTracking.res +4 -4
- package/src/SafeCheckpointTracking.res.mjs +1 -1
- package/src/SimulateItems.res +26 -42
- package/src/SimulateItems.res.mjs +16 -40
- package/src/StagedRows.res +106 -0
- package/src/StagedRows.res.mjs +102 -0
- package/src/Staging.res +32 -14
- package/src/Staging.res.mjs +17 -20
- package/src/Storage.res +277 -998
- package/src/Storage.res.mjs +216 -731
- package/src/Supervisor.res +75 -56
- package/src/Supervisor.res.mjs +55 -26
- package/src/TestIndexer.res +22 -27
- package/src/TestIndexer.res.mjs +20 -17
- package/src/Throttler.res +15 -8
- package/src/Throttler.res.mjs +9 -6
- package/src/Throttler.resi +1 -1
- package/src/UserContext.res +46 -410
- package/src/UserContext.res.mjs +30 -318
- package/src/Utils.res +0 -23
- package/src/Utils.res.mjs +1 -17
- package/src/Writing.res +0 -1
- package/src/Writing.res.mjs +1 -1
- package/src/bindings/ClickHouse.res +0 -322
- package/src/bindings/ClickHouse.res.mjs +0 -338
- package/src/bindings/StorageClient.res +107 -175
- package/src/bindings/StorageClient.res.mjs +19 -8
- package/src/bindings/Vitest.res +0 -26
- package/src/bindings/Vitest.res.mjs +0 -3
- package/src/db/Table.res +24 -150
- package/src/db/Table.res.mjs +38 -272
- package/src/sources/AddressSet.res +0 -2
- package/src/sources/AddressStore.res +0 -3
- package/src/sources/ChainSources.res +2 -0
- package/src/sources/ChainSources.res.mjs +2 -2
- package/src/sources/EvmChain.res +4 -7
- package/src/sources/EvmChain.res.mjs +5 -4
- package/src/sources/EvmHyperSyncSource.res +2 -2
- package/src/sources/EvmHyperSyncSource.res.mjs +1 -1
- package/src/sources/EvmRpcClient.res +13 -3
- package/src/sources/EvmRpcClient.res.mjs +4 -3
- package/src/sources/EvmRpcWs.res +4 -3
- package/src/sources/EvmRpcWs.res.mjs +2 -2
- package/src/sources/HeightFeed.res +31 -10
- package/src/sources/HeightFeed.res.mjs +10 -6
- package/src/sources/HeightStream.res +32 -17
- package/src/sources/HeightStream.res.mjs +10 -10
- package/src/sources/HyperSync.res +1 -2
- package/src/sources/HyperSync.res.mjs +1 -2
- package/src/sources/HyperSyncSSE.res +4 -6
- package/src/sources/HyperSyncSSE.res.mjs +2 -2
- package/src/sources/RpcSource.res +10 -1
- package/src/sources/RpcSource.res.mjs +4 -3
- package/src/sources/Source.res +3 -0
- package/src/sources/SourceManager.res +85 -104
- package/src/sources/SourceManager.res.mjs +18 -37
- package/src/sources/SourceManager.resi +3 -5
- package/src/sources/StartBlockResolver.res +1 -0
- package/src/sources/StartBlockResolver.res.mjs +4 -3
- package/src/sources/SvmHyperSyncSource.res +2 -2
- package/src/sources/SvmHyperSyncSource.res.mjs +1 -1
- package/svm.schema.json +3 -3
- package/src/EffectCacheLookup.res +0 -98
- package/src/EffectCacheLookup.res.mjs +0 -116
- package/src/PgWriting.res +0 -36
- package/src/PgWriting.res.mjs +0 -34
- package/src/PreloadLookahead.res +0 -184
- package/src/PreloadLookahead.res.mjs +0 -197
- package/src/SubgraphLog.res +0 -19
- package/src/SubgraphLog.res.mjs +0 -26
- package/src/SyncWrites.res +0 -101
- package/src/SyncWrites.res.mjs +0 -98
- package/src/db/IndexDefinition.res +0 -47
- package/src/db/IndexDefinition.res.mjs +0 -60
- package/src/sources/CallSource.res +0 -274
- package/src/sources/CallSource.res.mjs +0 -196
- package/src/subgraph/abi-types.ts +0 -84
- package/src/subgraph/aggregations.ts +0 -745
- package/src/subgraph/as-package.ts +0 -143
- package/src/subgraph/assemblyscript-regex.ts +0 -67
- package/src/subgraph/assemblyscript.ts +0 -731
- package/src/subgraph/blocks.ts +0 -398
- package/src/subgraph/calls-source.ts +0 -702
- package/src/subgraph/calls.ts +0 -258
- package/src/subgraph/conformance.ts +0 -106
- package/src/subgraph/errors.ts +0 -85
- package/src/subgraph/graft.ts +0 -73
- package/src/subgraph/graph-cli-worker.mjs +0 -35
- package/src/subgraph/graph-cli.ts +0 -900
- package/src/subgraph/graph-node-decimal.ts +0 -199
- package/src/subgraph/graph-ts-enums.ts +0 -28
- package/src/subgraph/graph-ts-types/VERSION +0 -2
- package/src/subgraph/graph-ts-types/chain/arweave.d.ts +0 -70
- package/src/subgraph/graph-ts-types/chain/cosmos.d.ts +0 -327
- package/src/subgraph/graph-ts-types/chain/ethereum.d.ts +0 -233
- package/src/subgraph/graph-ts-types/chain/near.d.ts +0 -253
- package/src/subgraph/graph-ts-types/chain/starknet.d.ts +0 -32
- package/src/subgraph/graph-ts-types/common/collections.d.ts +0 -136
- package/src/subgraph/graph-ts-types/common/conversion.d.ts +0 -11
- package/src/subgraph/graph-ts-types/common/datasource.d.ts +0 -30
- package/src/subgraph/graph-ts-types/common/eager-offset.d.ts +0 -0
- package/src/subgraph/graph-ts-types/common/json.d.ts +0 -17
- package/src/subgraph/graph-ts-types/common/numbers.d.ts +0 -120
- package/src/subgraph/graph-ts-types/common/value.d.ts +0 -120
- package/src/subgraph/graph-ts-types/common/yaml.d.ts +0 -90
- package/src/subgraph/graph-ts-types/global/global.d.ts +0 -194
- package/src/subgraph/graph-ts-types/helper-functions.d.ts +0 -22
- package/src/subgraph/graph-ts-types/index.d.ts +0 -102
- package/src/subgraph/graph-ts.ts +0 -4280
- package/src/subgraph/hosts.ts +0 -554
- package/src/subgraph/log.ts +0 -28
- package/src/subgraph/receipts.ts +0 -184
- package/src/subgraph/register-slots.ts +0 -93
- package/src/subgraph/rollup.ts +0 -109
- package/src/subgraph/rpc.ts +0 -337
- package/src/subgraph/runtime.ts +0 -2060
- package/src/subgraph/scope.ts +0 -177
- package/src/subgraph/stats.ts +0 -42
- package/src/subgraph/template-instances.ts +0 -66
- package/src/subgraph/toolchain.ts +0 -327
- package/src/subgraph/transient.ts +0 -176
|
@@ -1,325 +1,3 @@
|
|
|
1
|
-
let fieldTypeName = (fieldType: Table.fieldType) =>
|
|
2
|
-
switch fieldType {
|
|
3
|
-
| String => "String"
|
|
4
|
-
| Boolean => "Boolean"
|
|
5
|
-
| Uint32 => "Uint32"
|
|
6
|
-
| UInt52 => "UInt52"
|
|
7
|
-
| SmallInt =>
|
|
8
|
-
JsError.throwWithMessage("ClickHouse doesn't support the internal SmallInt column type")
|
|
9
|
-
| Bytea => "Bytea"
|
|
10
|
-
| UInt64 => "UInt64"
|
|
11
|
-
| Int32 => "Int32"
|
|
12
|
-
| ChainId => "ChainId"
|
|
13
|
-
| Number => "Number"
|
|
14
|
-
| Serial => "Serial"
|
|
15
|
-
| BigSerial => "BigSerial"
|
|
16
|
-
| Json => "Json"
|
|
17
|
-
| Date => "Date"
|
|
18
|
-
| BigInt(_) => "BigInt"
|
|
19
|
-
| BigDecimal(_) => "BigDecimal"
|
|
20
|
-
| Enum(_) => "Enum"
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
let column = (
|
|
24
|
-
~name,
|
|
25
|
-
~rowName=?,
|
|
26
|
-
~fieldName=?,
|
|
27
|
-
~fieldType: Table.fieldType,
|
|
28
|
-
~isNullable=false,
|
|
29
|
-
~isArray=false,
|
|
30
|
-
): StorageClient.clickHouseColumn => {
|
|
31
|
-
name,
|
|
32
|
-
?rowName,
|
|
33
|
-
?fieldName,
|
|
34
|
-
fieldType: fieldType->fieldTypeName,
|
|
35
|
-
isNullable,
|
|
36
|
-
isArray,
|
|
37
|
-
precision: ?switch fieldType {
|
|
38
|
-
| BigInt({?precision}) => precision
|
|
39
|
-
| BigDecimal({?config}) => config->Option.map(((precision, _)) => precision)
|
|
40
|
-
| _ => None
|
|
41
|
-
},
|
|
42
|
-
scale: ?switch fieldType {
|
|
43
|
-
| BigDecimal({?config}) => config->Option.map(((_, scale)) => scale)
|
|
44
|
-
| _ => None
|
|
45
|
-
},
|
|
46
|
-
enumVariants: ?switch fieldType {
|
|
47
|
-
| Enum({config}) =>
|
|
48
|
-
Some(config.variants->Array.map(variant => variant->(Utils.magic: Table.enum => string)))
|
|
49
|
-
| _ => None
|
|
50
|
-
},
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
let fieldColumn = (field: Table.field) =>
|
|
54
|
-
column(
|
|
55
|
-
~name=field->Table.getClickHouseDbFieldName,
|
|
56
|
-
~rowName=field->Table.getPgDbFieldName,
|
|
57
|
-
~fieldName=field.fieldName,
|
|
58
|
-
~fieldType=field.fieldType,
|
|
59
|
-
~isNullable=field.isNullable,
|
|
60
|
-
~isArray=field.isArray,
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
let entityTable = (entityConfig: Internal.entityConfig): StorageClient.clickHouseTable => {
|
|
64
|
-
let options = entityConfig.storage.clickhouseOptions
|
|
65
|
-
{
|
|
66
|
-
name: entityConfig.name,
|
|
67
|
-
historyTable: EntityHistory.historyTableName(
|
|
68
|
-
~entityName=entityConfig.name,
|
|
69
|
-
~entityIndex=entityConfig.index,
|
|
70
|
-
),
|
|
71
|
-
columns: entityConfig.table.fields->Array.filterMap(field =>
|
|
72
|
-
switch field {
|
|
73
|
-
| Table.Field(f) => Some(fieldColumn(f))
|
|
74
|
-
| DerivedFrom(_) => None
|
|
75
|
-
}
|
|
76
|
-
),
|
|
77
|
-
chainIdColumn: ?(
|
|
78
|
-
entityConfig.table->Table.getChainIdField->Option.map(Table.getClickHouseDbFieldName)
|
|
79
|
-
),
|
|
80
|
-
partitionBy: ?(options->Option.flatMap(options => options.partitionBy)),
|
|
81
|
-
orderBy: ?(options->Option.flatMap(options => options.orderBy)),
|
|
82
|
-
ttl: ?(options->Option.flatMap(options => options.ttl)),
|
|
83
|
-
skippingIndexes: ?(
|
|
84
|
-
options->Option.flatMap(options =>
|
|
85
|
-
options.skippingIndexes->Option.map(indexes =>
|
|
86
|
-
indexes->Array.map(
|
|
87
|
-
(index): StorageClient.skippingIndex => {
|
|
88
|
-
name: index.name,
|
|
89
|
-
expr: index.expr,
|
|
90
|
-
indexType: index.type_,
|
|
91
|
-
granularity: ?index.granularity,
|
|
92
|
-
},
|
|
93
|
-
)
|
|
94
|
-
)
|
|
95
|
-
)
|
|
96
|
-
),
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Visits every node on the way into JSON text. A bigint would make
|
|
101
|
-
// `JSON.stringify` throw and fail the whole batch, so it travels as its digits.
|
|
102
|
-
%%private(
|
|
103
|
-
let jsonSafe = (~column) =>
|
|
104
|
-
(_, value: JSON.t) =>
|
|
105
|
-
switch value->typeof {
|
|
106
|
-
| #bigint =>
|
|
107
|
-
value->(Utils.magic: JSON.t => unknown)->Staging.stringOf->(Utils.magic: string => JSON.t)
|
|
108
|
-
// A Uint8Array inside a list column travels as its byte values, which the
|
|
109
|
-
// addon reads back into raw bytes.
|
|
110
|
-
| #object =>
|
|
111
|
-
switch value->(Utils.magic: JSON.t => unknown)->Utils.Bytes.asUint8Array {
|
|
112
|
-
| Some(bytes) =>
|
|
113
|
-
bytes
|
|
114
|
-
->(Utils.magic: Uint8Array.t => Array.arrayLike<int>)
|
|
115
|
-
->Array.fromArrayLike
|
|
116
|
-
->(Utils.magic: array<int> => JSON.t)
|
|
117
|
-
| None => value
|
|
118
|
-
}
|
|
119
|
-
| #number =>
|
|
120
|
-
let _ = value->(Utils.magic: JSON.t => float)->Staging.finiteOrThrow(~column)
|
|
121
|
-
value
|
|
122
|
-
| _ => value
|
|
123
|
-
}
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
type cell = Change.t<Internal.entity> => unknown
|
|
127
|
-
|
|
128
|
-
type historyCells = {
|
|
129
|
-
setCells: array<cell>,
|
|
130
|
-
deleteCells: array<cell>,
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
type table = {
|
|
134
|
-
handle: int,
|
|
135
|
-
name: string,
|
|
136
|
-
columns: array<Staging.column>,
|
|
137
|
-
// An entity's history cells, by the scope whose chain id they stamp.
|
|
138
|
-
historyCells: dict<historyCells>,
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
let makeTable = (~handle, ~name, {names, kinds, nullable}: StorageClient.clickHouseRegistered) => {
|
|
142
|
-
handle,
|
|
143
|
-
name,
|
|
144
|
-
columns: names->Array.mapWithIndex((name, index): Staging.column => {
|
|
145
|
-
name,
|
|
146
|
-
kind: kinds->Array.getUnsafe(index)->Staging.kindOfOrdinal,
|
|
147
|
-
isNullable: nullable->Array.getUnsafe(index),
|
|
148
|
-
replacer: Replacer(jsonSafe(~column=name)),
|
|
149
|
-
}),
|
|
150
|
-
historyCells: Dict.make(),
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// A Json column holds the document's text. Staging writes a string as is, so a
|
|
154
|
-
// document that is a string has to become its own JSON text here, or it would
|
|
155
|
-
// read back as something JSON can't parse. JSON `null` and an absent value are
|
|
156
|
-
// both stored as `null`: the column is never Nullable.
|
|
157
|
-
%%private(
|
|
158
|
-
let documentText = (value: unknown) =>
|
|
159
|
-
switch value->(Utils.magic: unknown => Nullable.t<JSON.t>) {
|
|
160
|
-
| Value(_) => value->Sql.canonicalDocument->(Utils.magic: string => unknown)
|
|
161
|
-
| Null | Undefined => "null"->(Utils.magic: string => unknown)
|
|
162
|
-
}
|
|
163
|
-
)
|
|
164
|
-
|
|
165
|
-
%%private(
|
|
166
|
-
let compileSerializer = schema =>
|
|
167
|
-
S.compile(schema, ~input=Value, ~output=Json, ~typeValidation=false, ~mode=Sync)->(
|
|
168
|
-
Utils.magic: (unknown => JSON.t) => unknown => unknown
|
|
169
|
-
)
|
|
170
|
-
)
|
|
171
|
-
|
|
172
|
-
%%private(
|
|
173
|
-
let documentsText = (f: Table.field): (unknown => unknown) =>
|
|
174
|
-
if f.isArray {
|
|
175
|
-
value =>
|
|
176
|
-
switch value->(Utils.magic: unknown => Nullable.t<array<unknown>>) {
|
|
177
|
-
| Value(documents) =>
|
|
178
|
-
documents->Array.map(documentText)->(Utils.magic: array<unknown> => unknown)
|
|
179
|
-
| Null | Undefined => value
|
|
180
|
-
}
|
|
181
|
-
} else {
|
|
182
|
-
documentText
|
|
183
|
-
}
|
|
184
|
-
)
|
|
185
|
-
|
|
186
|
-
%%private(
|
|
187
|
-
let serializerOf = (f: Table.field): (unknown => unknown) => {
|
|
188
|
-
let shaped = baseSchema =>
|
|
189
|
-
if f.isNullable {
|
|
190
|
-
Utils.Schema.nullTolerant(baseSchema)->S.toUnknown
|
|
191
|
-
} else if f.isArray {
|
|
192
|
-
S.array(baseSchema)->S.toUnknown
|
|
193
|
-
} else {
|
|
194
|
-
baseSchema
|
|
195
|
-
}
|
|
196
|
-
switch f.fieldType {
|
|
197
|
-
| Json => documentsText(f)
|
|
198
|
-
| Date => compileSerializer(shaped(Utils.Schema.clickHouseDate->S.toUnknown))
|
|
199
|
-
| Bytea => compileSerializer(shaped(S.json(~validate=false)->S.toUnknown))
|
|
200
|
-
| ChainId => compileSerializer(ChainId.schema->S.toUnknown)
|
|
201
|
-
| _ => compileSerializer(f.fieldSchema)
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
)
|
|
205
|
-
|
|
206
|
-
@get external changeEntity: Change.t<Internal.entity> => dict<unknown> = "entity"
|
|
207
|
-
|
|
208
|
-
%%private(let absent: unknown = %raw(`undefined`))
|
|
209
|
-
|
|
210
|
-
%%private(
|
|
211
|
-
let makeHistoryCells = (
|
|
212
|
-
table,
|
|
213
|
-
~entityConfig: Internal.entityConfig,
|
|
214
|
-
~scope: Internal.chainScope,
|
|
215
|
-
): historyCells => {
|
|
216
|
-
let sourceTable = entityConfig.table
|
|
217
|
-
let chainIdTag = switch (
|
|
218
|
-
sourceTable->Table.getChainIdField,
|
|
219
|
-
scope->Internal.chainScopeChainId,
|
|
220
|
-
) {
|
|
221
|
-
| (Some(field), Some(chainId)) =>
|
|
222
|
-
Some((field->Table.getClickHouseDbFieldName, chainId->(Utils.magic: ChainId.t => unknown)))
|
|
223
|
-
| _ => None
|
|
224
|
-
}
|
|
225
|
-
let fieldsByColumn = Dict.make()
|
|
226
|
-
sourceTable.fields->Array.forEach(field =>
|
|
227
|
-
switch field {
|
|
228
|
-
| Table.Field(f) => fieldsByColumn->Dict.set(f->Table.getClickHouseDbFieldName, f)
|
|
229
|
-
| DerivedFrom(_) => ()
|
|
230
|
-
}
|
|
231
|
-
)
|
|
232
|
-
|
|
233
|
-
let setCells = []
|
|
234
|
-
let deleteCells = []
|
|
235
|
-
let registeredNames = table.columns->Array.map(column => column.name)->Utils.Set.fromArray
|
|
236
|
-
table.columns->Array.forEach(({name}) => {
|
|
237
|
-
let (set, delete) = if name === EntityHistory.checkpointIdFieldName {
|
|
238
|
-
let cell = change => change->Change.getCheckpointId->(Utils.magic: bigint => unknown)
|
|
239
|
-
(cell, cell)
|
|
240
|
-
} else if name === EntityHistory.changeFieldName {
|
|
241
|
-
(
|
|
242
|
-
_ => (EntityHistory.RowAction.SET :> string)->(Utils.magic: string => unknown),
|
|
243
|
-
_ => (EntityHistory.RowAction.DELETE :> string)->(Utils.magic: string => unknown),
|
|
244
|
-
)
|
|
245
|
-
} else {
|
|
246
|
-
switch (chainIdTag, fieldsByColumn->Utils.Dict.dangerouslyGetNonOption(name)) {
|
|
247
|
-
| (Some((column, chainId)), _) if column === name => (_ => chainId, _ => chainId)
|
|
248
|
-
| (_, Some(f)) =>
|
|
249
|
-
let serialize = serializerOf(f)
|
|
250
|
-
let apiName = f->Table.getApiFieldName
|
|
251
|
-
if apiName === Table.idFieldName {
|
|
252
|
-
let cell = change =>
|
|
253
|
-
serialize(change->Change.getEntityId->(Utils.magic: EntityId.t => unknown))
|
|
254
|
-
(cell, cell)
|
|
255
|
-
} else {
|
|
256
|
-
(change => serialize(change->changeEntity->Dict.getUnsafe(apiName)), _ => absent)
|
|
257
|
-
}
|
|
258
|
-
| (_, None) =>
|
|
259
|
-
JsError.throwWithMessage(
|
|
260
|
-
`ClickHouse table "${table.name}" registered a column "${name}" that entity "${entityConfig.name}" has no value for`,
|
|
261
|
-
)
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
setCells->Array.push(set)
|
|
265
|
-
deleteCells->Array.push(delete)
|
|
266
|
-
})
|
|
267
|
-
|
|
268
|
-
fieldsByColumn->Dict.forEachWithKey((f, column) =>
|
|
269
|
-
if !(registeredNames->Utils.Set.has(column)) {
|
|
270
|
-
JsError.throwWithMessage(
|
|
271
|
-
`ClickHouse table "${table.name}" registered no column for field "${f.fieldName}" of entity "${entityConfig.name}"`,
|
|
272
|
-
)
|
|
273
|
-
}
|
|
274
|
-
)
|
|
275
|
-
|
|
276
|
-
{setCells, deleteCells}
|
|
277
|
-
}
|
|
278
|
-
)
|
|
279
|
-
|
|
280
|
-
// Every change as a row of the entity's history: a deletion keeps only the
|
|
281
|
-
// columns that say which entity it removed.
|
|
282
|
-
let stageChangesOrThrow = (
|
|
283
|
-
arena,
|
|
284
|
-
table,
|
|
285
|
-
~entityConfig: Internal.entityConfig,
|
|
286
|
-
~scope: Internal.chainScope,
|
|
287
|
-
~changes: array<Change.t<Internal.entity>>,
|
|
288
|
-
) => {
|
|
289
|
-
let stage =
|
|
290
|
-
arena->Staging.begin(~table=table.handle, ~rows=changes->Array.length, ~columns=table.columns)
|
|
291
|
-
try {
|
|
292
|
-
let cacheKey = scope->Internal.chainScopeToString
|
|
293
|
-
let cells = switch table.historyCells->Utils.Dict.dangerouslyGetNonOption(cacheKey) {
|
|
294
|
-
| Some(cached) => cached
|
|
295
|
-
| None =>
|
|
296
|
-
let cells = table->makeHistoryCells(~entityConfig, ~scope)
|
|
297
|
-
table.historyCells->Dict.set(cacheKey, cells)
|
|
298
|
-
cells
|
|
299
|
-
}
|
|
300
|
-
let columns = stage->Staging.columnCount
|
|
301
|
-
changes->Array.forEachWithIndex((change, row) => {
|
|
302
|
-
let (cells, write) = switch change {
|
|
303
|
-
| Change.Set(_) => (cells.setCells, Staging.writeValue)
|
|
304
|
-
| Delete(_) => (cells.deleteCells, Staging.writeDeletedValue)
|
|
305
|
-
}
|
|
306
|
-
for column in 0 to columns - 1 {
|
|
307
|
-
stage->write(~column, ~row, (cells->Array.getUnsafe(column))(change))
|
|
308
|
-
}
|
|
309
|
-
})
|
|
310
|
-
stage->Staging.commit
|
|
311
|
-
} catch {
|
|
312
|
-
| exn =>
|
|
313
|
-
stage->Staging.abort
|
|
314
|
-
throw(
|
|
315
|
-
Persistence.StorageError({
|
|
316
|
-
message: `Failed to convert items for ClickHouse table "${table.name}"`,
|
|
317
|
-
reason: exn->Utils.prettifyExn,
|
|
318
|
-
}),
|
|
319
|
-
)
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
1
|
// Every connection setting has to be there: an unset one would otherwise reach
|
|
324
2
|
// the server as an empty value and fail there, for a reason naming neither.
|
|
325
3
|
let optionsFromEnvOrThrow = (): StorageClient.clickHouseOptions => {
|
|
@@ -1,340 +1,8 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as Env from "../Env.res.mjs";
|
|
4
|
-
import * as Sql from "../db/Sql.res.mjs";
|
|
5
|
-
import * as Table from "../db/Table.res.mjs";
|
|
6
4
|
import * as Utils from "../Utils.res.mjs";
|
|
7
|
-
import * as ChainId from "../ChainId.res.mjs";
|
|
8
|
-
import * as Staging from "../Staging.res.mjs";
|
|
9
|
-
import * as Internal from "../Internal.res.mjs";
|
|
10
|
-
import * as Persistence from "../Persistence.res.mjs";
|
|
11
|
-
import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
|
|
12
|
-
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
13
|
-
import * as EntityHistory from "../db/EntityHistory.res.mjs";
|
|
14
|
-
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
15
5
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
16
|
-
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
17
|
-
import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
|
|
18
|
-
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
19
|
-
|
|
20
|
-
function fieldTypeName(fieldType) {
|
|
21
|
-
if (typeof fieldType !== "object") {
|
|
22
|
-
switch (fieldType) {
|
|
23
|
-
case "String" :
|
|
24
|
-
return "String";
|
|
25
|
-
case "Boolean" :
|
|
26
|
-
return "Boolean";
|
|
27
|
-
case "Uint32" :
|
|
28
|
-
return "Uint32";
|
|
29
|
-
case "UInt52" :
|
|
30
|
-
return "UInt52";
|
|
31
|
-
case "SmallInt" :
|
|
32
|
-
return Stdlib_JsError.throwWithMessage("ClickHouse doesn't support the internal SmallInt column type");
|
|
33
|
-
case "Bytea" :
|
|
34
|
-
return "Bytea";
|
|
35
|
-
case "UInt64" :
|
|
36
|
-
return "UInt64";
|
|
37
|
-
case "Int32" :
|
|
38
|
-
return "Int32";
|
|
39
|
-
case "ChainId" :
|
|
40
|
-
return "ChainId";
|
|
41
|
-
case "Number" :
|
|
42
|
-
return "Number";
|
|
43
|
-
case "Serial" :
|
|
44
|
-
return "Serial";
|
|
45
|
-
case "BigSerial" :
|
|
46
|
-
return "BigSerial";
|
|
47
|
-
case "Json" :
|
|
48
|
-
return "Json";
|
|
49
|
-
case "Date" :
|
|
50
|
-
return "Date";
|
|
51
|
-
}
|
|
52
|
-
} else {
|
|
53
|
-
switch (fieldType.type) {
|
|
54
|
-
case "BigInt" :
|
|
55
|
-
return "BigInt";
|
|
56
|
-
case "BigDecimal" :
|
|
57
|
-
return "BigDecimal";
|
|
58
|
-
case "Enum" :
|
|
59
|
-
return "Enum";
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function column(name, rowName, fieldName, fieldType, isNullableOpt, isArrayOpt) {
|
|
65
|
-
let isNullable = isNullableOpt !== undefined ? isNullableOpt : false;
|
|
66
|
-
let isArray = isArrayOpt !== undefined ? isArrayOpt : false;
|
|
67
|
-
let tmp;
|
|
68
|
-
if (typeof fieldType !== "object") {
|
|
69
|
-
tmp = undefined;
|
|
70
|
-
} else {
|
|
71
|
-
switch (fieldType.type) {
|
|
72
|
-
case "BigInt" :
|
|
73
|
-
tmp = fieldType.precision;
|
|
74
|
-
break;
|
|
75
|
-
case "BigDecimal" :
|
|
76
|
-
tmp = Stdlib_Option.map(fieldType.config, param => param[0]);
|
|
77
|
-
break;
|
|
78
|
-
default:
|
|
79
|
-
tmp = undefined;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
let tmp$1;
|
|
83
|
-
tmp$1 = typeof fieldType !== "object" || fieldType.type !== "BigDecimal" ? undefined : Stdlib_Option.map(fieldType.config, param => param[1]);
|
|
84
|
-
let tmp$2;
|
|
85
|
-
tmp$2 = typeof fieldType !== "object" || fieldType.type !== "Enum" ? undefined : fieldType.config.variants.map(variant => variant);
|
|
86
|
-
return {
|
|
87
|
-
name: name,
|
|
88
|
-
rowName: rowName,
|
|
89
|
-
fieldName: fieldName,
|
|
90
|
-
fieldType: fieldTypeName(fieldType),
|
|
91
|
-
isNullable: isNullable,
|
|
92
|
-
isArray: isArray,
|
|
93
|
-
precision: tmp,
|
|
94
|
-
scale: tmp$1,
|
|
95
|
-
enumVariants: tmp$2
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
function fieldColumn(field) {
|
|
100
|
-
return column(Table.getClickHouseDbFieldName(field), Table.getPgDbFieldName(field), field.fieldName, field.fieldType, field.isNullable, field.isArray);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function entityTable(entityConfig) {
|
|
104
|
-
let options = entityConfig.storage.clickhouseOptions;
|
|
105
|
-
return {
|
|
106
|
-
name: entityConfig.name,
|
|
107
|
-
historyTable: EntityHistory.historyTableName(entityConfig.name, entityConfig.index),
|
|
108
|
-
columns: Stdlib_Array.filterMap(entityConfig.table.fields, field => {
|
|
109
|
-
if (field.TAG === "Field") {
|
|
110
|
-
return fieldColumn(field._0);
|
|
111
|
-
}
|
|
112
|
-
}),
|
|
113
|
-
chainIdColumn: Stdlib_Option.map(Table.getChainIdField(entityConfig.table), Table.getClickHouseDbFieldName),
|
|
114
|
-
partitionBy: Stdlib_Option.flatMap(options, options => options.partitionBy),
|
|
115
|
-
orderBy: Stdlib_Option.flatMap(options, options => options.orderBy),
|
|
116
|
-
ttl: Stdlib_Option.flatMap(options, options => options.ttl),
|
|
117
|
-
skippingIndexes: Stdlib_Option.flatMap(options, options => Stdlib_Option.map(options.skippingIndexes, indexes => indexes.map(index => ({
|
|
118
|
-
name: index.name,
|
|
119
|
-
expr: index.expr,
|
|
120
|
-
indexType: index.type,
|
|
121
|
-
granularity: index.granularity
|
|
122
|
-
}))))
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function jsonSafe(column) {
|
|
127
|
-
return (param, value) => {
|
|
128
|
-
let match = typeof value;
|
|
129
|
-
if (match === "bigint") {
|
|
130
|
-
return String(value);
|
|
131
|
-
}
|
|
132
|
-
if (match !== "object") {
|
|
133
|
-
if (match === "number") {
|
|
134
|
-
Staging.finiteOrThrow(value, column);
|
|
135
|
-
return value;
|
|
136
|
-
} else {
|
|
137
|
-
return value;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
let bytes = Utils.Bytes.asUint8Array(value);
|
|
141
|
-
if (bytes !== undefined) {
|
|
142
|
-
return Array.from(bytes);
|
|
143
|
-
} else {
|
|
144
|
-
return value;
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
function makeTable(handle, name, param) {
|
|
150
|
-
let nullable = param.nullable;
|
|
151
|
-
let kinds = param.kinds;
|
|
152
|
-
return {
|
|
153
|
-
handle: handle,
|
|
154
|
-
name: name,
|
|
155
|
-
columns: param.names.map((name, index) => ({
|
|
156
|
-
name: name,
|
|
157
|
-
kind: Staging.kindOfOrdinal(kinds[index]),
|
|
158
|
-
isNullable: nullable[index],
|
|
159
|
-
replacer: jsonSafe(name)
|
|
160
|
-
})),
|
|
161
|
-
historyCells: {}
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
function documentText(value) {
|
|
166
|
-
if (value == null) {
|
|
167
|
-
return "null";
|
|
168
|
-
} else {
|
|
169
|
-
return Sql.canonicalDocument(value);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
function compileSerializer(schema) {
|
|
174
|
-
return S$RescriptSchema.compile(schema, "Output", "Json", "Sync", false);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
function serializerOf(f) {
|
|
178
|
-
let shaped = baseSchema => {
|
|
179
|
-
if (f.isNullable) {
|
|
180
|
-
return Utils.Schema.nullTolerant(baseSchema);
|
|
181
|
-
} else if (f.isArray) {
|
|
182
|
-
return S$RescriptSchema.array(baseSchema);
|
|
183
|
-
} else {
|
|
184
|
-
return baseSchema;
|
|
185
|
-
}
|
|
186
|
-
};
|
|
187
|
-
let match = f.fieldType;
|
|
188
|
-
if (typeof match === "object") {
|
|
189
|
-
return compileSerializer(f.fieldSchema);
|
|
190
|
-
}
|
|
191
|
-
switch (match) {
|
|
192
|
-
case "Bytea" :
|
|
193
|
-
return compileSerializer(shaped(S$RescriptSchema.json(false)));
|
|
194
|
-
case "ChainId" :
|
|
195
|
-
return compileSerializer(ChainId.schema);
|
|
196
|
-
case "Json" :
|
|
197
|
-
if (f.isArray) {
|
|
198
|
-
return value => {
|
|
199
|
-
if (value == null) {
|
|
200
|
-
return value;
|
|
201
|
-
} else {
|
|
202
|
-
return value.map(documentText);
|
|
203
|
-
}
|
|
204
|
-
};
|
|
205
|
-
} else {
|
|
206
|
-
return documentText;
|
|
207
|
-
}
|
|
208
|
-
case "Date" :
|
|
209
|
-
return compileSerializer(shaped(Utils.Schema.clickHouseDate));
|
|
210
|
-
default:
|
|
211
|
-
return compileSerializer(f.fieldSchema);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
let absent = undefined;
|
|
216
|
-
|
|
217
|
-
function makeHistoryCells(table, entityConfig, scope) {
|
|
218
|
-
let sourceTable = entityConfig.table;
|
|
219
|
-
let match = Table.getChainIdField(sourceTable);
|
|
220
|
-
let match$1 = Internal.chainScopeChainId(scope);
|
|
221
|
-
let chainIdTag = match !== undefined && match$1 !== undefined ? [
|
|
222
|
-
Table.getClickHouseDbFieldName(match),
|
|
223
|
-
Primitive_option.valFromOption(match$1)
|
|
224
|
-
] : undefined;
|
|
225
|
-
let fieldsByColumn = {};
|
|
226
|
-
sourceTable.fields.forEach(field => {
|
|
227
|
-
if (field.TAG !== "Field") {
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
let f = field._0;
|
|
231
|
-
fieldsByColumn[Table.getClickHouseDbFieldName(f)] = f;
|
|
232
|
-
});
|
|
233
|
-
let setCells = [];
|
|
234
|
-
let deleteCells = [];
|
|
235
|
-
let registeredNames = new Set(table.columns.map(column => column.name));
|
|
236
|
-
table.columns.forEach(param => {
|
|
237
|
-
let name = param.name;
|
|
238
|
-
let match;
|
|
239
|
-
if (name === EntityHistory.checkpointIdFieldName) {
|
|
240
|
-
let cell = change => change.checkpointId;
|
|
241
|
-
match = [
|
|
242
|
-
cell,
|
|
243
|
-
cell
|
|
244
|
-
];
|
|
245
|
-
} else if (name === EntityHistory.changeFieldName) {
|
|
246
|
-
match = [
|
|
247
|
-
param => "SET",
|
|
248
|
-
param => "DELETE"
|
|
249
|
-
];
|
|
250
|
-
} else {
|
|
251
|
-
let match$1 = fieldsByColumn[name];
|
|
252
|
-
let exit = 0;
|
|
253
|
-
if (chainIdTag !== undefined && chainIdTag[0] === name) {
|
|
254
|
-
let chainId = chainIdTag[1];
|
|
255
|
-
match = [
|
|
256
|
-
param => chainId,
|
|
257
|
-
param => chainId
|
|
258
|
-
];
|
|
259
|
-
} else {
|
|
260
|
-
exit = 1;
|
|
261
|
-
}
|
|
262
|
-
if (exit === 1) {
|
|
263
|
-
if (match$1 !== undefined) {
|
|
264
|
-
let serialize = serializerOf(match$1);
|
|
265
|
-
let apiName = Table.getApiFieldName(match$1);
|
|
266
|
-
if (apiName === Table.idFieldName) {
|
|
267
|
-
let cell$1 = change => serialize(change.entityId);
|
|
268
|
-
match = [
|
|
269
|
-
cell$1,
|
|
270
|
-
cell$1
|
|
271
|
-
];
|
|
272
|
-
} else {
|
|
273
|
-
match = [
|
|
274
|
-
change => serialize(change.entity[apiName]),
|
|
275
|
-
param => absent
|
|
276
|
-
];
|
|
277
|
-
}
|
|
278
|
-
} else {
|
|
279
|
-
match = Stdlib_JsError.throwWithMessage(`ClickHouse table "` + table.name + `" registered a column "` + name + `" that entity "` + entityConfig.name + `" has no value for`);
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
setCells.push(match[0]);
|
|
284
|
-
deleteCells.push(match[1]);
|
|
285
|
-
});
|
|
286
|
-
Stdlib_Dict.forEachWithKey(fieldsByColumn, (f, column) => {
|
|
287
|
-
if (!registeredNames.has(column)) {
|
|
288
|
-
return Stdlib_JsError.throwWithMessage(`ClickHouse table "` + table.name + `" registered no column for field "` + f.fieldName + `" of entity "` + entityConfig.name + `"`);
|
|
289
|
-
}
|
|
290
|
-
});
|
|
291
|
-
return {
|
|
292
|
-
setCells: setCells,
|
|
293
|
-
deleteCells: deleteCells
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
function stageChangesOrThrow(arena, table, entityConfig, scope, changes) {
|
|
298
|
-
let stage = Staging.begin(arena, table.handle, changes.length, table.columns);
|
|
299
|
-
try {
|
|
300
|
-
let cacheKey = Internal.chainScopeToString(scope);
|
|
301
|
-
let cached = table.historyCells[cacheKey];
|
|
302
|
-
let cells;
|
|
303
|
-
if (cached !== undefined) {
|
|
304
|
-
cells = cached;
|
|
305
|
-
} else {
|
|
306
|
-
let cells$1 = makeHistoryCells(table, entityConfig, scope);
|
|
307
|
-
table.historyCells[cacheKey] = cells$1;
|
|
308
|
-
cells = cells$1;
|
|
309
|
-
}
|
|
310
|
-
let columns = Staging.columnCount(stage);
|
|
311
|
-
changes.forEach((change, row) => {
|
|
312
|
-
let match;
|
|
313
|
-
match = change.type === "SET" ? [
|
|
314
|
-
cells.setCells,
|
|
315
|
-
Staging.writeValue
|
|
316
|
-
] : [
|
|
317
|
-
cells.deleteCells,
|
|
318
|
-
Staging.writeDeletedValue
|
|
319
|
-
];
|
|
320
|
-
let write = match[1];
|
|
321
|
-
let cells$2 = match[0];
|
|
322
|
-
for (let column = 0; column < columns; ++column) {
|
|
323
|
-
write(stage, column, row, cells$2[column](change));
|
|
324
|
-
}
|
|
325
|
-
});
|
|
326
|
-
return Staging.commit(stage);
|
|
327
|
-
} catch (raw_exn) {
|
|
328
|
-
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
329
|
-
Staging.abort(stage);
|
|
330
|
-
throw {
|
|
331
|
-
RE_EXN_ID: Persistence.StorageError,
|
|
332
|
-
message: `Failed to convert items for ClickHouse table "` + table.name + `"`,
|
|
333
|
-
reason: Utils.prettifyExn(exn),
|
|
334
|
-
Error: new Error()
|
|
335
|
-
};
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
6
|
|
|
339
7
|
function optionsFromEnvOrThrow() {
|
|
340
8
|
let missing = [];
|
|
@@ -364,12 +32,6 @@ function optionsFromEnvOrThrow() {
|
|
|
364
32
|
}
|
|
365
33
|
|
|
366
34
|
export {
|
|
367
|
-
fieldTypeName,
|
|
368
|
-
column,
|
|
369
|
-
fieldColumn,
|
|
370
|
-
entityTable,
|
|
371
|
-
makeTable,
|
|
372
|
-
stageChangesOrThrow,
|
|
373
35
|
optionsFromEnvOrThrow,
|
|
374
36
|
}
|
|
375
37
|
/* Env Not a pure module */
|