envio 3.15.0 → 3.16.0-subgraph

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.
Files changed (186) hide show
  1. package/README.md +40 -34
  2. package/evm.schema.json +11 -2
  3. package/fuel.schema.json +10 -1
  4. package/index.d.ts +6 -0
  5. package/licenses/README.md +1 -1
  6. package/package.json +10 -9
  7. package/src/Batch.res.mjs +5 -5
  8. package/src/BatchProcessing.res +1 -0
  9. package/src/BatchProcessing.res.mjs +1 -0
  10. package/src/Bin.res +7 -0
  11. package/src/Bin.res.mjs +8 -0
  12. package/src/ChainFetching.res +450 -16
  13. package/src/ChainFetching.res.mjs +403 -32
  14. package/src/ChainState.res +124 -7
  15. package/src/ChainState.res.mjs +128 -67
  16. package/src/ChainState.resi +26 -0
  17. package/src/Clock.res +57 -0
  18. package/src/Clock.res.mjs +72 -0
  19. package/src/Config.res +31 -3
  20. package/src/Config.res.mjs +15 -4
  21. package/src/ContractRegisterContext.res +3 -6
  22. package/src/ContractRegisterContext.res.mjs +4 -2
  23. package/src/Core.res +95 -36
  24. package/src/Core.res.mjs +90 -1
  25. package/src/CrossChainState.res +12 -2
  26. package/src/CrossChainState.res.mjs +3 -3
  27. package/src/Ecosystem.res +7 -4
  28. package/src/Ecosystem.res.mjs +8 -8
  29. package/src/EffectCacheLookup.res +98 -0
  30. package/src/EffectCacheLookup.res.mjs +116 -0
  31. package/src/EffectState.res +10 -2
  32. package/src/EffectState.res.mjs +8 -4
  33. package/src/EffectState.resi +3 -1
  34. package/src/EntityId.res +2 -7
  35. package/src/EntityId.res.mjs +1 -8
  36. package/src/EntityTables.res +4 -1
  37. package/src/EntityTables.res.mjs +1 -1
  38. package/src/Env.res +20 -0
  39. package/src/Env.res.mjs +16 -0
  40. package/src/EventProcessing.res +38 -1
  41. package/src/EventProcessing.res.mjs +28 -1
  42. package/src/FetchState.res +408 -73
  43. package/src/FetchState.res.mjs +361 -91
  44. package/src/FinalizeBackfill.res +2 -4
  45. package/src/FinalizeBackfill.res.mjs +3 -4
  46. package/src/HandlerLoader.res +39 -15
  47. package/src/HandlerLoader.res.mjs +27 -8
  48. package/src/HandlerRegister.res +4 -0
  49. package/src/HandlerRegister.res.mjs +5 -2
  50. package/src/HandlerRegister.resi +2 -0
  51. package/src/InMemoryTable.res +17 -16
  52. package/src/InMemoryTable.res.mjs +14 -15
  53. package/src/IndexerState.res +28 -4
  54. package/src/IndexerState.res.mjs +19 -6
  55. package/src/IndexerState.resi +4 -0
  56. package/src/Internal.res +61 -49
  57. package/src/Internal.res.mjs +36 -80
  58. package/src/LoadLayer.res +54 -15
  59. package/src/LoadLayer.res.mjs +75 -45
  60. package/src/LoadLayer.resi +26 -0
  61. package/src/Main.res +14 -1
  62. package/src/Main.res.mjs +4 -3
  63. package/src/Persistence.res +3 -23
  64. package/src/Persistence.res.mjs +3 -3
  65. package/src/PreloadLookahead.res +202 -0
  66. package/src/PreloadLookahead.res.mjs +218 -0
  67. package/src/Rollback.res +0 -1
  68. package/src/Rollback.res.mjs +1 -1
  69. package/src/RunScope.res +3 -0
  70. package/src/SafeCheckpointTracking.res +4 -4
  71. package/src/SafeCheckpointTracking.res.mjs +1 -1
  72. package/src/SimulateItems.res +42 -26
  73. package/src/SimulateItems.res.mjs +40 -16
  74. package/src/StagedRows.res +106 -0
  75. package/src/StagedRows.res.mjs +102 -0
  76. package/src/Staging.res +32 -14
  77. package/src/Staging.res.mjs +17 -20
  78. package/src/Storage.res +303 -948
  79. package/src/Storage.res.mjs +229 -708
  80. package/src/SubgraphLog.res +19 -0
  81. package/src/SubgraphLog.res.mjs +26 -0
  82. package/src/Supervisor.res +75 -56
  83. package/src/Supervisor.res.mjs +55 -26
  84. package/src/SyncWrites.res +107 -0
  85. package/src/SyncWrites.res.mjs +98 -0
  86. package/src/TestIndexer.res +22 -27
  87. package/src/TestIndexer.res.mjs +20 -17
  88. package/src/Throttler.res +15 -8
  89. package/src/Throttler.res.mjs +9 -6
  90. package/src/Throttler.resi +1 -1
  91. package/src/UserContext.res +419 -46
  92. package/src/UserContext.res.mjs +318 -30
  93. package/src/Utils.res +17 -6
  94. package/src/Utils.res.mjs +12 -6
  95. package/src/Writing.res +0 -1
  96. package/src/Writing.res.mjs +1 -1
  97. package/src/bindings/ClickHouse.res +0 -322
  98. package/src/bindings/ClickHouse.res.mjs +0 -338
  99. package/src/bindings/StorageClient.res +108 -174
  100. package/src/bindings/StorageClient.res.mjs +19 -8
  101. package/src/bindings/Vitest.res +0 -26
  102. package/src/bindings/Vitest.res.mjs +0 -3
  103. package/src/db/Table.res +24 -150
  104. package/src/db/Table.res.mjs +38 -272
  105. package/src/sources/AddressSet.res +2 -0
  106. package/src/sources/AddressStore.res +3 -0
  107. package/src/sources/CallSource.res +274 -0
  108. package/src/sources/CallSource.res.mjs +196 -0
  109. package/src/sources/ChainSources.res +2 -0
  110. package/src/sources/ChainSources.res.mjs +2 -2
  111. package/src/sources/EvmChain.res +10 -1
  112. package/src/sources/EvmChain.res.mjs +6 -3
  113. package/src/sources/EvmHyperSyncSource.res +2 -2
  114. package/src/sources/EvmHyperSyncSource.res.mjs +1 -1
  115. package/src/sources/EvmRpcClient.res +13 -3
  116. package/src/sources/EvmRpcClient.res.mjs +4 -3
  117. package/src/sources/EvmRpcWs.res +4 -3
  118. package/src/sources/EvmRpcWs.res.mjs +2 -2
  119. package/src/sources/HeightFeed.res +31 -10
  120. package/src/sources/HeightFeed.res.mjs +10 -6
  121. package/src/sources/HeightStream.res +32 -17
  122. package/src/sources/HeightStream.res.mjs +10 -10
  123. package/src/sources/HyperSync.res +2 -1
  124. package/src/sources/HyperSync.res.mjs +2 -1
  125. package/src/sources/HyperSyncSSE.res +4 -6
  126. package/src/sources/HyperSyncSSE.res.mjs +2 -2
  127. package/src/sources/RpcSource.res +10 -1
  128. package/src/sources/RpcSource.res.mjs +4 -3
  129. package/src/sources/Source.res +3 -0
  130. package/src/sources/SourceManager.res +84 -77
  131. package/src/sources/SourceManager.res.mjs +17 -20
  132. package/src/sources/SourceManager.resi +3 -4
  133. package/src/sources/StartBlockResolver.res +1 -0
  134. package/src/sources/StartBlockResolver.res.mjs +3 -2
  135. package/src/sources/SvmHyperSyncSource.res +2 -2
  136. package/src/sources/SvmHyperSyncSource.res.mjs +1 -1
  137. package/src/subgraph/abi-types.ts +84 -0
  138. package/src/subgraph/aggregations.ts +745 -0
  139. package/src/subgraph/as-package.ts +143 -0
  140. package/src/subgraph/assemblyscript-regex.ts +67 -0
  141. package/src/subgraph/assemblyscript.ts +731 -0
  142. package/src/subgraph/blocks.ts +398 -0
  143. package/src/subgraph/calls-source.ts +702 -0
  144. package/src/subgraph/calls.ts +258 -0
  145. package/src/subgraph/conformance.ts +106 -0
  146. package/src/subgraph/errors.ts +85 -0
  147. package/src/subgraph/graft.ts +73 -0
  148. package/src/subgraph/graph-cli-worker.mjs +35 -0
  149. package/src/subgraph/graph-cli.ts +900 -0
  150. package/src/subgraph/graph-node-decimal.ts +199 -0
  151. package/src/subgraph/graph-ts-enums.ts +28 -0
  152. package/src/subgraph/graph-ts-types/VERSION +2 -0
  153. package/src/subgraph/graph-ts-types/chain/arweave.d.ts +70 -0
  154. package/src/subgraph/graph-ts-types/chain/cosmos.d.ts +327 -0
  155. package/src/subgraph/graph-ts-types/chain/ethereum.d.ts +233 -0
  156. package/src/subgraph/graph-ts-types/chain/near.d.ts +253 -0
  157. package/src/subgraph/graph-ts-types/chain/starknet.d.ts +32 -0
  158. package/src/subgraph/graph-ts-types/common/collections.d.ts +136 -0
  159. package/src/subgraph/graph-ts-types/common/conversion.d.ts +11 -0
  160. package/src/subgraph/graph-ts-types/common/datasource.d.ts +30 -0
  161. package/src/subgraph/graph-ts-types/common/eager-offset.d.ts +0 -0
  162. package/src/subgraph/graph-ts-types/common/json.d.ts +17 -0
  163. package/src/subgraph/graph-ts-types/common/numbers.d.ts +120 -0
  164. package/src/subgraph/graph-ts-types/common/value.d.ts +120 -0
  165. package/src/subgraph/graph-ts-types/common/yaml.d.ts +90 -0
  166. package/src/subgraph/graph-ts-types/global/global.d.ts +194 -0
  167. package/src/subgraph/graph-ts-types/helper-functions.d.ts +22 -0
  168. package/src/subgraph/graph-ts-types/index.d.ts +102 -0
  169. package/src/subgraph/graph-ts.ts +4339 -0
  170. package/src/subgraph/hosts.ts +554 -0
  171. package/src/subgraph/log.ts +28 -0
  172. package/src/subgraph/receipts.ts +184 -0
  173. package/src/subgraph/register-slots.ts +93 -0
  174. package/src/subgraph/rollup.ts +109 -0
  175. package/src/subgraph/rpc.ts +337 -0
  176. package/src/subgraph/runtime.ts +2059 -0
  177. package/src/subgraph/scope.ts +176 -0
  178. package/src/subgraph/stats.ts +42 -0
  179. package/src/subgraph/template-instances.ts +66 -0
  180. package/src/subgraph/toolchain.ts +327 -0
  181. package/src/subgraph/transient.ts +176 -0
  182. package/svm.schema.json +11 -2
  183. package/src/PgWriting.res +0 -36
  184. package/src/PgWriting.res.mjs +0 -34
  185. package/src/db/IndexDefinition.res +0 -47
  186. package/src/db/IndexDefinition.res.mjs +0 -67
@@ -1,18 +1,84 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
+ import * as Env from "./Env.res.mjs";
3
4
  import * as Utils from "./Utils.res.mjs";
4
5
  import * as Logger from "./Logger.res.mjs";
6
+ import * as ChainId from "./ChainId.res.mjs";
5
7
  import * as Internal from "./Internal.res.mjs";
6
8
  import * as RunScope from "./RunScope.res.mjs";
7
9
  import * as LoadLayer from "./LoadLayer.res.mjs";
10
+ import * as SyncWrites from "./SyncWrites.res.mjs";
8
11
  import * as EntityFilter from "./db/EntityFilter.res.mjs";
9
- import * as IndexerState from "./IndexerState.res.mjs";
10
12
  import * as InMemoryStore from "./InMemoryStore.res.mjs";
11
13
  import * as InMemoryTable from "./InMemoryTable.res.mjs";
12
14
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
13
15
  import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
16
+ import * as Stdlib_Promise from "@rescript/runtime/lib/es6/Stdlib_Promise.js";
17
+ import * as PreloadLookahead from "./PreloadLookahead.res.mjs";
14
18
  import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
15
19
  import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
20
+ import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
21
+
22
+ let Suspend = /* @__PURE__ */Primitive_exceptions.create("UserContext.Suspend");
23
+
24
+ function isSuspend(exn) {
25
+ return exn.RE_EXN_ID === Suspend;
26
+ }
27
+
28
+ let suspend = {
29
+ RE_EXN_ID: Suspend
30
+ };
31
+
32
+ let currentSync = {
33
+ contents: undefined
34
+ };
35
+
36
+ function syncOf(run) {
37
+ let sync = currentSync.contents;
38
+ if (sync !== undefined && sync.run === run) {
39
+ return sync;
40
+ }
41
+ }
42
+
43
+ function currentRunOrThrow(prop) {
44
+ let run = RunScope.currentHandlerRunOrThrow(prop);
45
+ let match = syncOf(run);
46
+ if (match !== undefined) {
47
+ let exn = match.status;
48
+ if (typeof exn === "object") {
49
+ throw exn._0;
50
+ }
51
+ }
52
+ return run;
53
+ }
54
+
55
+ function syncOrThrow(run, prop) {
56
+ let sync = syncOf(run);
57
+ if (sync !== undefined) {
58
+ return sync;
59
+ } else {
60
+ return Stdlib_JsError.throwWithMessage(`context.` + prop + ` is only available inside context.runSync.`);
61
+ }
62
+ }
63
+
64
+ function scheduleAndSuspend(sync, promise) {
65
+ sync.pending.push(promise);
66
+ sync.status = {
67
+ TAG: "Aborted",
68
+ _0: suspend
69
+ };
70
+ throw suspend;
71
+ }
72
+
73
+ function missOrSuspend(sync, promise, absent) {
74
+ if (sync.run.isPreload && sync.speculated < 32) {
75
+ sync.pending.push(promise);
76
+ sync.speculated = sync.speculated + 1 | 0;
77
+ return absent;
78
+ } else {
79
+ return scheduleAndSuspend(sync, promise);
80
+ }
81
+ }
16
82
 
17
83
  let effectContextPrototype = (Object.create(null));
18
84
 
@@ -46,7 +112,7 @@ function isCrossChain(params, effect) {
46
112
  return Stdlib_Option.getOr(effect.crossChain, params.config.defaultCrossChain);
47
113
  }
48
114
 
49
- function callEffect(params, run, caller, effect, input) {
115
+ function prepareEffectCall(params, run, caller, effect, input) {
50
116
  let handlerChainId = Internal.getItemChainId(run.item);
51
117
  let scope = isCrossChain(params, effect) ? "crossChain" : handlerChainId;
52
118
  if (caller !== undefined && scope !== "crossChain") {
@@ -61,13 +127,59 @@ function callEffect(params, run, caller, effect, input) {
61
127
  caller: run,
62
128
  effectName: effect.name
63
129
  });
64
- return LoadLayer.loadEffect(params.loadManager, params.persistence, effect, {
130
+ let effectArgs_cacheKey = Utils.Hash.boundCacheKey(Utils.Hash.makeOrThrow(S$RescriptSchema.reverseConvertOrThrow(input, effect.input)));
131
+ let effectArgs_checkpointId = run.checkpointId;
132
+ let effectArgs = {
65
133
  input: input,
66
134
  context: effectContext,
67
- cacheKey: Utils.Hash.makeOrThrow(S$RescriptSchema.reverseConvertOrThrow(input, effect.input)),
135
+ cacheKey: effectArgs_cacheKey,
68
136
  chainId: handlerChainId,
69
- checkpointId: run.checkpointId
70
- }, scope, params.indexerState, run.isPreload);
137
+ checkpointId: effectArgs_checkpointId
138
+ };
139
+ return [
140
+ scope,
141
+ effectArgs
142
+ ];
143
+ }
144
+
145
+ function callEffect(params, run, caller, effect, input) {
146
+ let match = prepareEffectCall(params, run, caller, effect, input);
147
+ return LoadLayer.loadEffect(params.loadManager, params.persistence, effect, match[1], match[0], params.indexerState, run.isPreload);
148
+ }
149
+
150
+ function effectMemoKey(effect, scope, cacheKey) {
151
+ if (scope === "crossChain") {
152
+ return effect.name + `.` + cacheKey;
153
+ } else {
154
+ return effect.name + `.` + ChainId.toString(scope) + `.` + cacheKey;
155
+ }
156
+ }
157
+
158
+ function effectSync(params, effect, input) {
159
+ let run = currentRunOrThrow("effectSync");
160
+ let sync = syncOrThrow(run, "effectSync");
161
+ let match = prepareEffectCall(params, run, undefined, effect, input);
162
+ let effectArgs = match[1];
163
+ let scope = match[0];
164
+ let memoKey = effectMemoKey(effect, scope, effectArgs.cacheKey);
165
+ let output = sync.memo[memoKey];
166
+ if (output !== undefined) {
167
+ return Primitive_option.valFromOption(output);
168
+ }
169
+ let inMemTable = InMemoryStore.getEffectInMemTable(params.indexerState, effect, scope);
170
+ if (InMemoryStore.hasEffectOutput(inMemTable, effectArgs.cacheKey)) {
171
+ let output$1 = InMemoryStore.getEffectOutputUnsafe(inMemTable, effectArgs.cacheKey);
172
+ sync.memo[memoKey] = output$1;
173
+ return output$1;
174
+ }
175
+ if (sync.speculated <= 0) {
176
+ return scheduleAndSuspend(sync, LoadLayer.loadEffect(params.loadManager, params.persistence, effect, effectArgs, scope, params.indexerState, run.isPreload));
177
+ }
178
+ sync.status = {
179
+ TAG: "Aborted",
180
+ _0: suspend
181
+ };
182
+ throw suspend;
71
183
  }
72
184
 
73
185
  function expiresUnread(entityConfig) {
@@ -85,35 +197,43 @@ function throwExpiresUnread(entityConfig, op) {
85
197
 
86
198
  function makeEntityContext(params, entityConfig) {
87
199
  let prop = entityConfig.name;
200
+ let entityName = entityConfig.name;
88
201
  let scopeOf = run => InMemoryStore.entityScope(entityConfig, Internal.getItemChainId(run.item));
89
202
  let loadById = entityId => {
90
- let run = RunScope.currentHandlerRunOrThrow(prop);
203
+ let run = currentRunOrThrow(prop);
91
204
  return LoadLayer.loadById(params.loadManager, params.persistence, entityConfig, scopeOf(run), params.indexerState, run.isPreload, entityId);
92
205
  };
93
206
  let write = (run, change) => {
94
- let scope = scopeOf(run);
95
- InMemoryTable.Entity.set(InMemoryStore.getInMemTable(params.indexerState, entityConfig, scope), IndexerState.committedCheckpointIdFor(params.indexerState, scope), change);
207
+ let match = syncOf(run);
208
+ let match$1 = run.isPreload;
209
+ if (match !== undefined) {
210
+ if (match$1 && !PreloadLookahead.isActive()) {
211
+ return;
212
+ } else {
213
+ return SyncWrites.record(match.writes, entityConfig, scopeOf(run), change);
214
+ }
215
+ } else if (match$1) {
216
+ return;
217
+ } else {
218
+ return SyncWrites.write(params.indexerState, entityConfig, scopeOf(run), change);
219
+ }
96
220
  };
97
221
  let set = entity => {
98
- let run = RunScope.currentHandlerRunOrThrow(prop);
99
- if (!run.isPreload) {
100
- return write(run, {
101
- type: "SET",
102
- entityId: entity.id,
103
- entity: entity,
104
- checkpointId: run.checkpointId
105
- });
106
- }
222
+ let run = currentRunOrThrow(prop);
223
+ write(run, {
224
+ type: "SET",
225
+ entityId: entity.id,
226
+ entity: entity,
227
+ checkpointId: run.checkpointId
228
+ });
107
229
  };
108
230
  let deleteUnsafe = entityId => {
109
- let run = RunScope.currentHandlerRunOrThrow(prop);
110
- if (!run.isPreload) {
111
- return write(run, {
112
- type: "DELETE",
113
- entityId: entityId,
114
- checkpointId: run.checkpointId
115
- });
116
- }
231
+ let run = currentRunOrThrow(prop);
232
+ write(run, {
233
+ type: "DELETE",
234
+ entityId: entityId,
235
+ checkpointId: run.checkpointId
236
+ });
117
237
  };
118
238
  let entityContext = expiresUnread(entityConfig) ? ({
119
239
  get: param => throwExpiresUnread(entityConfig, "get"),
@@ -125,7 +245,7 @@ function makeEntityContext(params, entityConfig) {
125
245
  }) : ({
126
246
  get: loadById,
127
247
  getWhere: filter => {
128
- let run = RunScope.currentHandlerRunOrThrow(prop);
248
+ let run = currentRunOrThrow(prop);
129
249
  return LoadLayer.loadByFilter(params.loadManager, params.persistence, entityConfig, scopeOf(run), params.indexerState, run.isPreload, filter);
130
250
  },
131
251
  getOrThrow: (entityId, message) => loadById(entityId).then(entity => {
@@ -146,7 +266,136 @@ function makeEntityContext(params, entityConfig) {
146
266
  set: set,
147
267
  deleteUnsafe: deleteUnsafe
148
268
  });
149
- return Object.assign(Object.create(Utils.StrictObject.makePrototype(op => Stdlib_JsError.throwWithMessage(`Invalid context.` + entityConfig.name + `.` + op + ` operation.`))), entityContext);
269
+ let object = Object.assign(Object.create(Utils.StrictObject.makePrototype(op => Stdlib_JsError.throwWithMessage(`Invalid context.` + entityConfig.name + `.` + op + ` operation.`))), entityContext);
270
+ if (!Env.subgraphMode.contents) {
271
+ return object;
272
+ }
273
+ let syncEntityContext_getSync = entityId => {
274
+ let run = currentRunOrThrow(prop);
275
+ let sync = syncOrThrow(run, prop + `.getSync`);
276
+ let scope = scopeOf(run);
277
+ let entityKey = entityConfig.table.entityIdToKey(entityId);
278
+ let entity = SyncWrites.getById(sync.writes, entityConfig, entityId);
279
+ if (entity !== undefined) {
280
+ return Primitive_option.valFromOption(entity);
281
+ }
282
+ let entity$1 = run.isPreload ? PreloadLookahead.overlayGet(run.item, entityName, scope, entityKey) : undefined;
283
+ if (entity$1 !== undefined) {
284
+ return Primitive_option.valFromOption(entity$1);
285
+ }
286
+ let entity$2 = LoadLayer.getByIdInMemory(entityConfig, scope, params.indexerState, entityId);
287
+ if (entity$2 === undefined) {
288
+ return missOrSuspend(sync, LoadLayer.loadById(params.loadManager, params.persistence, entityConfig, scope, params.indexerState, run.isPreload, entityId), undefined);
289
+ }
290
+ let entity$3 = Primitive_option.valFromOption(entity$2);
291
+ if (run.isPreload && Stdlib_Option.isNone(entity$3)) {
292
+ PreloadLookahead.recordAbsent(run.item, entityName, scope, entityKey);
293
+ }
294
+ return entity$3;
295
+ };
296
+ let syncEntityContext_getWhereSync = filter => {
297
+ let run = currentRunOrThrow(prop);
298
+ let sync = syncOrThrow(run, prop + `.getWhereSync`);
299
+ let scope = scopeOf(run);
300
+ let filter$1 = EntityFilter.parseOrThrow(filter, entityName, entityConfig.table);
301
+ let entities = LoadLayer.getByFilterInMemory(entityConfig, scope, params.indexerState, filter$1);
302
+ if (entities !== undefined) {
303
+ return SyncWrites.overlayFilter(sync.writes, entities, entityConfig, filter$1);
304
+ } else {
305
+ return missOrSuspend(sync, LoadLayer.loadByParsedFilter(params.loadManager, params.persistence, entityConfig, scope, params.indexerState, run.isPreload, filter$1), []);
306
+ }
307
+ };
308
+ let syncEntityContext_getInBlockSync = entityId => {
309
+ let run = currentRunOrThrow(prop);
310
+ let sync = syncOrThrow(run, prop + `.getInBlockSync`);
311
+ let entity = SyncWrites.getById(sync.writes, entityConfig, entityId);
312
+ if (entity !== undefined) {
313
+ return Primitive_option.valFromOption(entity);
314
+ }
315
+ let inMemTable = InMemoryStore.getInMemTable(params.indexerState, entityConfig, scopeOf(run));
316
+ let change = inMemTable.latestEntityChangeById[inMemTable.entityIdToKey(entityId)];
317
+ if (change !== undefined && change.checkpointId === run.checkpointId) {
318
+ return InMemoryTable.Entity.mapChangeToEntity(change);
319
+ }
320
+ };
321
+ let syncEntityContext = {
322
+ getSync: syncEntityContext_getSync,
323
+ getWhereSync: syncEntityContext_getWhereSync,
324
+ getInBlockSync: syncEntityContext_getInBlockSync
325
+ };
326
+ return Object.assign(object, syncEntityContext);
327
+ }
328
+
329
+ async function runSyncRound(params, sync, fn, round) {
330
+ if (round > 10000) {
331
+ Stdlib_JsError.throwWithMessage(`The handler suspended on a synchronous read too many times: gave up after ` + (10000).toString() + ` rounds. This usually means the code isn't deterministic across reruns.`);
332
+ }
333
+ let run = sync.run;
334
+ sync.status = "Active";
335
+ sync.pending = [];
336
+ sync.speculated = 0;
337
+ sync.writes = SyncWrites.make();
338
+ let startedAt = PreloadLookahead.roundStarted(run.isPreload);
339
+ let previous = currentSync.contents;
340
+ currentSync.contents = sync;
341
+ let outcome;
342
+ try {
343
+ fn();
344
+ outcome = {
345
+ TAG: "Ok",
346
+ _0: undefined
347
+ };
348
+ } catch (raw_exn) {
349
+ let exn = Primitive_exceptions.internalToException(raw_exn);
350
+ outcome = {
351
+ TAG: "Error",
352
+ _0: exn
353
+ };
354
+ }
355
+ currentSync.contents = previous;
356
+ PreloadLookahead.roundEnded(run.item, startedAt);
357
+ let writes = sync.writes;
358
+ sync.writes = SyncWrites.make();
359
+ let suspended;
360
+ if (outcome.TAG === "Ok") {
361
+ let match = sync.status;
362
+ if (typeof match !== "object" && sync.speculated <= 0) {
363
+ if (run.isPreload) {
364
+ SyncWrites.forEachChange(writes, (entityConfig, scope, change) => PreloadLookahead.overlaySet(run.item, entityConfig.name, scope, entityConfig.table.entityIdToKey(change.entityId), InMemoryTable.Entity.mapChangeToEntity(change)));
365
+ } else {
366
+ SyncWrites.commit(writes, params.indexerState);
367
+ }
368
+ suspended = false;
369
+ } else {
370
+ suspended = true;
371
+ }
372
+ } else {
373
+ let exn$1 = outcome._0;
374
+ if (exn$1.RE_EXN_ID === Suspend || sync.speculated > 0) {
375
+ suspended = true;
376
+ } else {
377
+ sync.pending.forEach(promise => {
378
+ promise.catch(param => {});
379
+ });
380
+ sync.pending = [];
381
+ throw exn$1;
382
+ }
383
+ }
384
+ if (!suspended) {
385
+ return;
386
+ }
387
+ let pending = sync.pending;
388
+ sync.pending = [];
389
+ let errors = [];
390
+ await Promise.all(pending.map(promise => Stdlib_Promise.$$catch(promise, exn => {
391
+ errors.push(exn);
392
+ return Promise.resolve();
393
+ })));
394
+ let exn$2 = errors[0];
395
+ if (exn$2 !== undefined) {
396
+ throw exn$2;
397
+ }
398
+ return await runSyncRound(params, sync, fn, round + 1 | 0);
150
399
  }
151
400
 
152
401
  function makeHandlerContext(params) {
@@ -154,7 +403,7 @@ function makeHandlerContext(params) {
154
403
  let define = (name, get) => {
155
404
  Object.defineProperty(context, name, {
156
405
  enumerable: true,
157
- get: () => get(RunScope.currentHandlerRunOrThrow(name))
406
+ get: () => get(currentRunOrThrow(name))
158
407
  });
159
408
  };
160
409
  define("log", run => {
@@ -164,11 +413,31 @@ function makeHandlerContext(params) {
164
413
  return Logger.asContextLog(RunScope.handlerLogger(run));
165
414
  }
166
415
  });
167
- let effect = (effect$1, input) => callEffect(params, RunScope.currentHandlerRunOrThrow("effect"), undefined, effect$1, input);
416
+ let effect = (effect$1, input) => callEffect(params, currentRunOrThrow("effect"), undefined, effect$1, input);
168
417
  Object.defineProperty(context, "effect", {
169
418
  enumerable: true,
170
419
  value: effect
171
420
  });
421
+ if (Env.subgraphMode.contents) {
422
+ Object.defineProperty(context, "effectSync", {
423
+ enumerable: true,
424
+ value: (effect, input) => effectSync(params, effect, input)
425
+ });
426
+ Object.defineProperty(context, "runSync", {
427
+ enumerable: true,
428
+ value: fn => {
429
+ let run = currentRunOrThrow("runSync");
430
+ return runSyncRound(params, {
431
+ run: run,
432
+ status: "Active",
433
+ pending: [],
434
+ memo: {},
435
+ writes: SyncWrites.make(),
436
+ speculated: 0
437
+ }, fn, 1);
438
+ }
439
+ });
440
+ }
172
441
  define("isPreload", run => run.isPreload);
173
442
  define("chain", run => params.chains[Internal.getItemChainId(run.item)]);
174
443
  Utils.Dict.forEachWithKey(params.config.userEntitiesByName, (entityConfig, name) => {
@@ -178,13 +447,32 @@ function makeHandlerContext(params) {
178
447
  return context;
179
448
  }
180
449
 
450
+ let maxSpeculatedReads = 32;
451
+
452
+ let maxSyncRounds = 10000;
453
+
181
454
  export {
455
+ Suspend,
456
+ isSuspend,
457
+ suspend,
458
+ currentSync,
459
+ syncOf,
460
+ currentRunOrThrow,
461
+ syncOrThrow,
462
+ scheduleAndSuspend,
463
+ maxSpeculatedReads,
464
+ missOrSuspend,
182
465
  effectContextPrototype,
183
466
  isCrossChain,
467
+ prepareEffectCall,
184
468
  callEffect,
469
+ effectMemoKey,
470
+ effectSync,
185
471
  expiresUnread,
186
472
  throwExpiresUnread,
187
473
  makeEntityContext,
474
+ maxSyncRounds,
475
+ runSyncRound,
188
476
  makeHandlerContext,
189
477
  }
190
478
  /* effectContextPrototype Not a pure module */
package/src/Utils.res CHANGED
@@ -10,12 +10,6 @@ external toMethod: 'a => 'a = "%unsafe_to_method"
10
10
 
11
11
  @val external importPath: string => promise<unknown> = "import"
12
12
 
13
- // Half the delay fixed, half spread across it. Every indexer pointed at one
14
- // provider loses its stream, or gives up on a quiet chain, in the same instant
15
- // that provider blinks, and putting them all back on the same schedule is how a
16
- // blip becomes a stampede.
17
- let jitter = delay => delay / 2 + (Math.random() *. (delay / 2)->Int.toFloat)->Float.toInt
18
-
19
13
  // Clearing a pending timer and forgetting it are one action. A ref left holding
20
14
  // a spent id reads as a timer still pending, and the next clear looks like it
21
15
  // did something.
@@ -887,6 +881,23 @@ module Hash = {
887
881
  (any->magic)["toString"]()
888
882
  }
889
883
  }
884
+
885
+ type sha256
886
+ @module("node:crypto") external createSha256: (@as("sha256") _, unit) => sha256 = "createHash"
887
+ @send external update: (sha256, string) => sha256 = "update"
888
+ @send external digestHex: (sha256, @as("hex") _) => string = "digest"
889
+ @val @scope("Buffer") external byteLength: string => int = "byteLength"
890
+
891
+ // A cache row is keyed by its effect's input, and a Postgres btree key takes
892
+ // at most 2704 bytes: a contract call with a large argument (calldata of a
893
+ // few kB) failed the batch write. Such inputs are keyed by their sha256;
894
+ // every shorter input keeps the key it always had.
895
+ let maxRawCacheKeyBytes = 2000
896
+
897
+ let boundCacheKey = (key: string) =>
898
+ key->byteLength > maxRawCacheKeyBytes
899
+ ? "sha256:" ++ createSha256()->update(key)->digestHex
900
+ : key
890
901
  }
891
902
 
892
903
  let prettifyExn = exn => {
package/src/Utils.res.mjs CHANGED
@@ -2,6 +2,7 @@ import packageJson from '../package.json' with { type: 'json' }
2
2
  // Generated by ReScript, PLEASE EDIT WITH CARE
3
3
 
4
4
  import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
5
+ import * as Nodecrypto from "node:crypto";
5
6
  import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
6
7
  import * as Stdlib_JsExn from "@rescript/runtime/lib/es6/Stdlib_JsExn.js";
7
8
  import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
@@ -13,10 +14,6 @@ import * as Primitive_string from "@rescript/runtime/lib/es6/Primitive_string.js
13
14
  import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
14
15
  import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
15
16
 
16
- function jitter(delay) {
17
- return (delay / 2 | 0) + (Math.random() * (delay / 2 | 0) | 0) | 0;
18
- }
19
-
20
17
  function clearTimeoutRef(timeoutId) {
21
18
  let id = timeoutId.contents;
22
19
  if (id !== undefined) {
@@ -748,9 +745,19 @@ function makeOrThrow(any) {
748
745
  return hash$1 + "}";
749
746
  }
750
747
 
748
+ function boundCacheKey(key) {
749
+ if (Buffer.byteLength(key) > 2000) {
750
+ return "sha256:" + Nodecrypto.createHash("sha256").update(key).digest("hex");
751
+ } else {
752
+ return key;
753
+ }
754
+ }
755
+
751
756
  let Hash = {
752
757
  fail: fail,
753
- makeOrThrow: makeOrThrow
758
+ makeOrThrow: makeOrThrow,
759
+ maxRawCacheKeyBytes: 2000,
760
+ boundCacheKey: boundCacheKey
754
761
  };
755
762
 
756
763
  function prettifyExn(exn) {
@@ -813,7 +820,6 @@ function replaceLoneSurrogateEscapes(json) {
813
820
  let maxBackoffExponent = 20;
814
821
 
815
822
  export {
816
- jitter,
817
823
  clearTimeoutRef,
818
824
  maxBackoffExponent,
819
825
  expBackoff,
package/src/Writing.res CHANGED
@@ -153,7 +153,6 @@ let runOneWrite = async (state: IndexerState.t) => {
153
153
  ~batch,
154
154
  ~rollback,
155
155
  ~config,
156
- ~allEntities=persistence.allEntities,
157
156
  ~updatedEntities,
158
157
  ~registeredAddresses,
159
158
  ~updatedEffectsCache,
@@ -121,7 +121,7 @@ async function runOneWrite(state) {
121
121
  });
122
122
  let pruneTargets = PruneStaleHistory.select(state, writtenEntityNames, Stdlib_Option.isSome(rollback));
123
123
  await Promise.all([
124
- persistence.storage.writeBatch(batch, rollback, config, persistence.allEntities, updatedEffectsCache, updatedEntities, registeredAddresses, chainMetaData, (storage, timeSeconds) => IndexerState.recordStorageWrite(state, storage, timeSeconds)),
124
+ persistence.storage.writeBatch(batch, rollback, config, updatedEffectsCache, updatedEntities, registeredAddresses, chainMetaData, (storage, timeSeconds) => IndexerState.recordStorageWrite(state, storage, timeSeconds)),
125
125
  PruneStaleHistory.runConcurrent(state, pruneTargets)
126
126
  ]);
127
127
  IndexerState.markCommitted(state, writtenFrontier);