-
Notifications
You must be signed in to change notification settings - Fork 72
/
ObjectActionHandler.js
79 lines (70 loc) · 2.89 KB
/
ObjectActionHandler.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/* ObjectActionHandler
* This is an example of an AbstractActionHandler implementation.
*
* The role of the Action Handler is to receive block data passed from the Action Reader, and populate some external
* state deterministically derived from that data, as well as trigger side-effects.
*
* The AbstractActionHandler has the following abstract methods:
*
* handleWithState(handle)
* Call the passed-in `handle` function with the object you would like to pass in as `state` to Updaters and Effects.
* In this example, we're just using a simple structured Javascript object, but in a real implementation this will
* most likely an interface to a database. See the API documentation for more details.
*
* updateIndexState(state, block)
* Besides some caching optimizations, the state of the progress of indexing is stored outside of Demux itself, and
* this method is implemented to store that data. The data needed to be stored is blockNumber, blockHash, isReplay,
* and handlerVersionName. the `state` object passed into the `handle` function of the above `handleWithState` is
* provided here as a convenience.
*
* loadIndexState()
* This returns an `IndexState` object containing all the information saved in the above method.
*
* rollbackTo(blockNumber)
* If indexing potentially reversible blocks, a mechanism for reverting back to a specific block is necessary.
* In this example, we keep a history of the entire state at every block, and load it when called.
*/
const { AbstractActionHandler } = require("demux")
// Initial state
let state = {
volumeBySymbol: {},
totalTransfers: 0,
indexState: {
blockNumber: 0,
blockHash: "",
isReplay: false,
handlerVersionName: "v1",
},
}
const stateHistory = {}
const stateHistoryMaxLength = 300
class ObjectActionHandler extends AbstractActionHandler {
async handleWithState(handle) {
await handle(state)
const { blockNumber } = state.indexState
stateHistory[blockNumber] = JSON.parse(JSON.stringify(state))
if (blockNumber > stateHistoryMaxLength && stateHistory[blockNumber - stateHistoryMaxLength]) {
delete stateHistory[blockNumber - stateHistoryMaxLength]
}
}
async loadIndexState() {
return state.indexState
}
async updateIndexState(stateObj, block, isReplay, handlerVersionName) {
stateObj.indexState.blockNumber = block.blockInfo.blockNumber
stateObj.indexState.blockHash = block.blockInfo.blockHash
stateObj.indexState.isReplay = isReplay
stateObj.indexState.handlerVersionName = handlerVersionName
}
async rollbackTo(blockNumber) {
const latestBlockNumber = state.indexState.blockNumber
const toDelete = [...Array(latestBlockNumber - (blockNumber)).keys()].map(n => n + blockNumber + 1)
for (const n of toDelete) {
delete stateHistory[n]
}
state = stateHistory[blockNumber]
}
async setup() {
}
}
module.exports = ObjectActionHandler