Comparing version 3.1.4-fd42365.0 to 4.0.0
@@ -1,3 +0,3 @@ | ||
import * as Logger from "bunyan"; | ||
import { Block, HandlerVersion, IndexState, NextBlock, VersionedAction } from "./interfaces"; | ||
import * as Logger from 'bunyan'; | ||
import { Block, HandlerInfo, HandlerVersion, IndexState, NextBlock, VersionedAction } from './interfaces'; | ||
/** | ||
@@ -11,6 +11,7 @@ * Takes `block`s output from implementations of `AbstractActionReader` and processes their actions through the | ||
export declare abstract class AbstractActionHandler { | ||
protected lastProcessedBlockNumber: number; | ||
protected lastProcessedBlockHash: string; | ||
protected handlerVersionName: string; | ||
lastProcessedBlockNumber: number; | ||
lastProcessedBlockHash: string; | ||
handlerVersionName: string; | ||
protected log: Logger; | ||
protected initialized: boolean; | ||
private deferredEffects; | ||
@@ -28,2 +29,10 @@ private handlerVersionMap; | ||
/** | ||
* Information about the current state of the Action Handler | ||
*/ | ||
readonly info: HandlerInfo; | ||
/** | ||
* Performs all required initialization for the handler. | ||
*/ | ||
initialize(): Promise<void>; | ||
/** | ||
* Updates the `lastProcessedBlockNumber` and `lastProcessedBlockHash` meta state, coinciding with the block | ||
@@ -47,2 +56,6 @@ * that has just been processed. These are the same values read by `updateIndexState()`. | ||
/** | ||
* Idempotently performs any required setup. | ||
*/ | ||
protected abstract setup(): Promise<void>; | ||
/** | ||
* This method is used when matching the types of incoming actions against the types the `Updater`s and `Effect`s are | ||
@@ -79,2 +92,3 @@ * subscribed to. When this returns true, their corresponding functions will run. | ||
protected handleActions(state: any, context: any, nextBlock: NextBlock, isReplay: boolean): Promise<void>; | ||
private handleRollback; | ||
private range; | ||
@@ -84,2 +98,3 @@ private runOrDeferEffect; | ||
private getNextDeferredBlockNumber; | ||
private rollbackDeferredEffects; | ||
private initHandlerVersions; | ||
@@ -86,0 +101,0 @@ private refreshIndexState; |
@@ -19,2 +19,3 @@ "use strict"; | ||
const Logger = __importStar(require("bunyan")); | ||
const errors_1 = require("./errors"); | ||
/** | ||
@@ -34,8 +35,9 @@ * Takes `block`s output from implementations of `AbstractActionReader` and processes their actions through the | ||
this.lastProcessedBlockNumber = 0; | ||
this.lastProcessedBlockHash = ""; | ||
this.handlerVersionName = "v1"; | ||
this.lastProcessedBlockHash = ''; | ||
this.handlerVersionName = 'v1'; | ||
this.initialized = false; | ||
this.deferredEffects = {}; | ||
this.handlerVersionMap = {}; | ||
this.initHandlerVersions(handlerVersions); | ||
this.log = Logger.createLogger({ name: "demux" }); | ||
this.log = Logger.createLogger({ name: 'demux' }); | ||
} | ||
@@ -50,12 +52,7 @@ /** | ||
const { isRollback, isEarliestBlock } = blockMeta; | ||
if (isRollback || (isReplay && isEarliestBlock)) { | ||
const rollbackBlockNumber = blockInfo.blockNumber - 1; | ||
const rollbackCount = this.lastProcessedBlockNumber - rollbackBlockNumber; | ||
this.log.info(`Rolling back ${rollbackCount} blocks to block ${rollbackBlockNumber}...`); | ||
yield this.rollbackTo(rollbackBlockNumber); | ||
yield this.refreshIndexState(); | ||
if (!this.initialized) { | ||
yield this.initialize(); | ||
this.initialized = true; | ||
} | ||
else if (this.lastProcessedBlockNumber === 0 && this.lastProcessedBlockHash === "") { | ||
yield this.refreshIndexState(); | ||
} | ||
yield this.handleRollback(isRollback, blockInfo.blockNumber, isReplay, isEarliestBlock); | ||
const nextBlockNeeded = this.lastProcessedBlockNumber + 1; | ||
@@ -78,3 +75,4 @@ // Just processed this block; skip | ||
if (blockInfo.previousBlockHash !== this.lastProcessedBlockHash) { | ||
throw Error("Block hashes do not match; block not part of current chain."); | ||
const err = new errors_1.MismatchedBlockHashError(); | ||
throw err; | ||
} | ||
@@ -90,2 +88,21 @@ } | ||
/** | ||
* Information about the current state of the Action Handler | ||
*/ | ||
get info() { | ||
return { | ||
lastProcessedBlockNumber: this.lastProcessedBlockNumber, | ||
lastProcessedBlockHash: this.lastProcessedBlockHash, | ||
handlerVersionName: this.handlerVersionName, | ||
}; | ||
} | ||
/** | ||
* Performs all required initialization for the handler. | ||
*/ | ||
initialize() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
yield this.setup(); | ||
yield this.refreshIndexState(); | ||
}); | ||
} | ||
/** | ||
* This method is used when matching the types of incoming actions against the types the `Updater`s and `Effect`s are | ||
@@ -169,2 +186,17 @@ * subscribed to. When this returns true, their corresponding functions will run. | ||
} | ||
handleRollback(isRollback, blockNumber, isReplay, isEarliestBlock) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (isRollback || (isReplay && isEarliestBlock)) { | ||
const rollbackBlockNumber = blockNumber - 1; | ||
const rollbackCount = this.lastProcessedBlockNumber - rollbackBlockNumber; | ||
this.log.info(`Rolling back ${rollbackCount} blocks to block ${rollbackBlockNumber}...`); | ||
yield this.rollbackTo(rollbackBlockNumber); | ||
this.rollbackDeferredEffects(blockNumber); | ||
yield this.refreshIndexState(); | ||
} | ||
else if (this.lastProcessedBlockNumber === 0 && this.lastProcessedBlockHash === '') { | ||
yield this.refreshIndexState(); | ||
} | ||
}); | ||
} | ||
range(start, end) { | ||
@@ -175,2 +207,3 @@ return Array(end - start).fill(0).map((_, i) => i + start); | ||
const { block, lastIrreversibleBlockNumber } = nextBlock; | ||
const { blockNumber } = block.blockInfo; | ||
const shouldRunImmediately = (!effect.deferUntilIrreversible || block.blockInfo.blockNumber <= lastIrreversibleBlockNumber); | ||
@@ -180,7 +213,7 @@ if (shouldRunImmediately) { | ||
} | ||
else if (!this.deferredEffects[block.blockInfo.blockNumber]) { | ||
this.deferredEffects[block.blockInfo.blockNumber] = [() => effect.run(payload, block, context)]; | ||
} | ||
else { | ||
this.deferredEffects[block.blockInfo.blockNumber].push(() => effect.run(payload, block, context)); | ||
if (!this.deferredEffects[blockNumber]) { | ||
this.deferredEffects[blockNumber] = []; | ||
} | ||
this.deferredEffects[blockNumber].push(() => effect.run(payload, block, context)); | ||
} | ||
@@ -195,3 +228,4 @@ } | ||
if (this.deferredEffects[blockNumber]) { | ||
for (const deferredEffect of this.deferredEffects[blockNumber]) { | ||
const effects = this.deferredEffects[blockNumber]; | ||
for (const deferredEffect of effects) { | ||
deferredEffect(); | ||
@@ -210,10 +244,16 @@ } | ||
} | ||
rollbackDeferredEffects(rollbackTo) { | ||
const blockNumbers = Object.keys(this.deferredEffects).map((num) => parseInt(num, 10)); | ||
const toRollBack = blockNumbers.filter((bn) => bn >= rollbackTo); | ||
for (const blockNumber of toRollBack) { | ||
delete this.deferredEffects[blockNumber]; | ||
} | ||
} | ||
initHandlerVersions(handlerVersions) { | ||
if (handlerVersions.length === 0) { | ||
throw new Error("Must have at least one handler version."); | ||
throw new errors_1.MissingHandlerVersionError(); | ||
} | ||
for (const handlerVersion of handlerVersions) { | ||
if (this.handlerVersionMap.hasOwnProperty(handlerVersion.versionName)) { | ||
throw new Error(`Handler version name '${handlerVersion.versionName}' already exists. ` + | ||
"Handler versions must have unique names."); | ||
throw new errors_1.DuplicateHandlerVersionError(handlerVersion.versionName); | ||
} | ||
@@ -226,3 +266,3 @@ this.handlerVersionMap[handlerVersion.versionName] = handlerVersion; | ||
} | ||
else if (handlerVersions[0].versionName !== "v1") { | ||
else if (handlerVersions[0].versionName !== 'v1') { | ||
this.warnIncorrectFirstHandler(handlerVersions[0].versionName); | ||
@@ -262,1 +302,2 @@ } | ||
exports.AbstractActionHandler = AbstractActionHandler; | ||
//# sourceMappingURL=AbstractActionHandler.js.map |
@@ -1,3 +0,3 @@ | ||
import * as Logger from "bunyan"; | ||
import { ActionReaderOptions, Block, NextBlock } from "./interfaces"; | ||
import * as Logger from 'bunyan'; | ||
import { ActionReaderOptions, Block, NextBlock, ReaderInfo } from './interfaces'; | ||
/** | ||
@@ -15,3 +15,3 @@ * Reads blocks from a blockchain, outputting normalized `Block` objects. | ||
protected log: Logger; | ||
private initialized; | ||
protected initialized: boolean; | ||
constructor(options?: ActionReaderOptions); | ||
@@ -41,2 +41,6 @@ /** | ||
/** | ||
* Performs all required initialization for the reader. | ||
*/ | ||
initialize(): Promise<void>; | ||
/** | ||
* Changes the state of the `AbstractActionReader` instance to have just processed the block at the given block | ||
@@ -50,2 +54,10 @@ * number. If the block exists in its temporary block history, it will use this, otherwise it will fetch the block | ||
/** | ||
* Information about the current state of the Action Reader | ||
*/ | ||
readonly info: ReaderInfo; | ||
/** | ||
* Idempotently performs any required setup. | ||
*/ | ||
protected abstract setup(): Promise<void>; | ||
/** | ||
* Incrementally rolls back reader state one block at a time, comparing the blockHistory with | ||
@@ -52,0 +64,0 @@ * newly fetched blocks. Fork resolution is finished when either the current block's previous hash |
@@ -19,7 +19,8 @@ "use strict"; | ||
const Logger = __importStar(require("bunyan")); | ||
const errors_1 = require("./errors"); | ||
const defaultBlock = { | ||
blockInfo: { | ||
blockNumber: 0, | ||
blockHash: "", | ||
previousBlockHash: "", | ||
blockHash: '', | ||
previousBlockHash: '', | ||
timestamp: new Date(0), | ||
@@ -43,3 +44,3 @@ }, | ||
this.onlyIrreversible = optionsWithDefaults.onlyIrreversible; | ||
this.log = Logger.createLogger({ name: "demux" }); | ||
this.log = Logger.createLogger({ name: 'demux' }); | ||
} | ||
@@ -60,6 +61,5 @@ /** | ||
}; | ||
// TODO: Should this only be called when updating headBlockNumber? | ||
this.lastIrreversibleBlockNumber = yield this.getLastIrreversibleBlockNumber(); | ||
if (!this.initialized) { | ||
yield this.initBlockState(); | ||
yield this.initialize(); | ||
} | ||
@@ -97,2 +97,12 @@ if (this.currentBlockNumber === this.headBlockNumber) { | ||
/** | ||
* Performs all required initialization for the reader. | ||
*/ | ||
initialize() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
yield this.setup(); | ||
yield this.initBlockState(); | ||
this.initialized = true; | ||
}); | ||
} | ||
/** | ||
* Changes the state of the `AbstractActionReader` instance to have just processed the block at the given block | ||
@@ -108,6 +118,6 @@ * number. If the block exists in its temporary block history, it will use this, otherwise it will fetch the block | ||
if (blockNumber < this.startAtBlock) { | ||
throw new Error("Cannot seek to block before configured `startAtBlock` number."); | ||
throw new errors_1.ImproperStartAtBlockError(); | ||
} | ||
if (blockNumber > this.headBlockNumber) { | ||
throw new Error(`Cannot seek to block number ${blockNumber} as it does not exist yet.`); | ||
throw new errors_1.ImproperSeekToBlockError(blockNumber); | ||
} | ||
@@ -119,2 +129,14 @@ this.currentBlockNumber = blockNumber - 1; | ||
/** | ||
* Information about the current state of the Action Reader | ||
*/ | ||
get info() { | ||
return { | ||
currentBlockNumber: this.currentBlockNumber, | ||
startAtBlock: this.startAtBlock, | ||
headBlockNumber: this.headBlockNumber, | ||
onlyIrreversible: this.onlyIrreversible, | ||
lastIrreversibleBlockNumber: this.lastIrreversibleBlockNumber, | ||
}; | ||
} | ||
/** | ||
* Incrementally rolls back reader state one block at a time, comparing the blockHistory with | ||
@@ -155,2 +177,3 @@ * newly fetched blocks. Fork resolution is finished when either the current block's previous hash | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this.lastIrreversibleBlockNumber = yield this.getLastIrreversibleBlockNumber(); | ||
this.headBlockNumber = yield this.getLatestNeededBlockNumber(); | ||
@@ -162,3 +185,2 @@ if (this.currentBlockNumber < 0) { | ||
yield this.reloadHistory(); | ||
this.initialized = true; | ||
}); | ||
@@ -240,3 +262,3 @@ } | ||
if (tryCount === maxTries) { | ||
throw new Error("Could not reload history."); | ||
throw new errors_1.ReloadHistoryError(); | ||
} | ||
@@ -250,3 +272,3 @@ } | ||
if (this.currentBlockData.blockInfo.blockNumber < this.lastIrreversibleBlockNumber && checkIrreversiblility) { | ||
throw new Error("Last irreversible block has been passed without resolving fork"); | ||
throw new errors_1.UnresolvedForkError(); | ||
} | ||
@@ -257,3 +279,3 @@ this.blockHistory.push(yield this.getBlock(this.currentBlockData.blockInfo.blockNumber - 1)); | ||
logForkDetected(unvalidatedBlockData, expectedHash, actualHash) { | ||
this.log.info("!! FORK DETECTED !!"); | ||
this.log.info('!! FORK DETECTED !!'); | ||
this.log.info(` MISMATCH:`); | ||
@@ -264,9 +286,9 @@ this.log.info(` ✓ NEW Block ${unvalidatedBlockData.blockInfo.blockNumber} previous: ${actualHash}`); | ||
logForkResolved(currentBlockInfo, previousBlockInfo) { | ||
this.log.info(" MATCH:"); | ||
this.log.info(' MATCH:'); | ||
this.log.info(` ✓ NEW Block ${currentBlockInfo.blockNumber} previous: ${currentBlockInfo.previousBlockHash}`); // tslint:disable-line | ||
this.log.info(` ✓ OLD Block ${previousBlockInfo.blockNumber} id: ${previousBlockInfo.blockHash}`); | ||
this.log.info("!! FORK RESOLVED !!"); | ||
this.log.info('!! FORK RESOLVED !!'); | ||
} | ||
logForkMismatch(currentBlockInfo, previousBlockInfo) { | ||
this.log.info(" MISMATCH:"); | ||
this.log.info(' MISMATCH:'); | ||
this.log.info(` ✓ NEW Block ${currentBlockInfo.blockNumber} previous: ${currentBlockInfo.previousBlockHash}`); | ||
@@ -277,1 +299,2 @@ this.log.info(` ✕ OLD Block ${previousBlockInfo.blockNumber} id: ${previousBlockInfo.blockHash}`); | ||
exports.AbstractActionReader = AbstractActionReader; | ||
//# sourceMappingURL=AbstractActionReader.js.map |
@@ -1,3 +0,5 @@ | ||
import { AbstractActionHandler } from "./AbstractActionHandler"; | ||
import { AbstractActionReader } from "./AbstractActionReader"; | ||
import * as Logger from 'bunyan'; | ||
import { AbstractActionHandler } from './AbstractActionHandler'; | ||
import { AbstractActionReader } from './AbstractActionReader'; | ||
import { DemuxInfo } from './interfaces'; | ||
/** | ||
@@ -16,2 +18,7 @@ * Coordinates implementations of `AbstractActionReader`s and `AbstractActionHandler`s in | ||
*/ | ||
protected log: Logger; | ||
private running; | ||
private shouldPause; | ||
private error; | ||
private clean; | ||
constructor(actionReader: AbstractActionReader, actionHandler: AbstractActionHandler, pollInterval: number); | ||
@@ -24,8 +31,25 @@ /** | ||
* Start a polling loop | ||
* | ||
* @param isReplay Set to true to disable Effects from running until caught up with head block. | ||
*/ | ||
watch(isReplay?: boolean): Promise<void>; | ||
/** | ||
* Start or resume indexing. | ||
*/ | ||
start(): boolean; | ||
/** | ||
* Suspend indexing. Will go into effect after the currently-processing block. | ||
*/ | ||
pause(): boolean; | ||
/** | ||
* Information about the current state of Demux | ||
*/ | ||
readonly info: DemuxInfo; | ||
/** | ||
* Use the actionReader and actionHandler to process new blocks. | ||
* | ||
* @param isReplay Set to true to disable Effects from running until caught up with head block. | ||
*/ | ||
protected checkForBlocks(isReplay?: boolean): Promise<void>; | ||
private readonly status; | ||
} |
@@ -10,3 +10,12 @@ "use strict"; | ||
}; | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; | ||
result["default"] = mod; | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const Logger = __importStar(require("bunyan")); | ||
const interfaces_1 = require("./interfaces"); | ||
/** | ||
@@ -17,7 +26,2 @@ * Coordinates implementations of `AbstractActionReader`s and `AbstractActionHandler`s in | ||
class BaseActionWatcher { | ||
/** | ||
* @param actionReader An instance of an implemented `AbstractActionReader` | ||
* @param actionHandler An instance of an implemented `AbstractActionHandler` | ||
* @param pollInterval Number of milliseconds between each polling loop iteration | ||
*/ | ||
constructor(actionReader, actionHandler, pollInterval) { | ||
@@ -27,2 +31,7 @@ this.actionReader = actionReader; | ||
this.pollInterval = pollInterval; | ||
this.running = false; | ||
this.shouldPause = false; | ||
this.error = null; | ||
this.clean = true; | ||
this.log = Logger.createLogger({ name: 'demux' }); | ||
} | ||
@@ -39,8 +48,29 @@ /** | ||
* Start a polling loop | ||
* | ||
* @param isReplay Set to true to disable Effects from running until caught up with head block. | ||
*/ | ||
watch(isReplay = false) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const startTime = new Date().getTime(); | ||
yield this.checkForBlocks(isReplay); | ||
const endTime = new Date().getTime(); | ||
if (this.shouldPause) { | ||
this.running = false; | ||
this.shouldPause = false; | ||
this.log.info('Indexing paused.'); | ||
return; | ||
} | ||
this.clean = false; | ||
this.running = true; | ||
this.error = null; | ||
const startTime = Date.now(); | ||
try { | ||
yield this.checkForBlocks(isReplay); | ||
} | ||
catch (err) { | ||
this.running = false; | ||
this.shouldPause = false; | ||
this.log.error(err); | ||
this.error = err; | ||
this.log.info('Indexing unexpectedly paused due to an error.'); | ||
return; | ||
} | ||
const endTime = Date.now(); | ||
const duration = endTime - startTime; | ||
@@ -55,3 +85,44 @@ let waitTime = this.pollInterval - duration; | ||
/** | ||
* Start or resume indexing. | ||
*/ | ||
start() { | ||
if (this.running) { | ||
this.log.info('Cannot start; already indexing.'); | ||
return false; | ||
} | ||
this.log.info('Starting indexing.'); | ||
// tslint:disable-next-line:no-floating-promises | ||
this.watch(); | ||
return true; | ||
} | ||
/** | ||
* Suspend indexing. Will go into effect after the currently-processing block. | ||
*/ | ||
pause() { | ||
if (!this.running) { | ||
this.log.info('Cannot pause; not currently indexing.'); | ||
return false; | ||
} | ||
this.log.info('Pausing indexing.'); | ||
this.shouldPause = true; | ||
return true; | ||
} | ||
/** | ||
* Information about the current state of Demux | ||
*/ | ||
get info() { | ||
const info = { | ||
handler: this.actionHandler.info, | ||
reader: this.actionReader.info, | ||
indexingStatus: this.status, | ||
}; | ||
if (this.error) { | ||
info.error = this.error; | ||
} | ||
return info; | ||
} | ||
/** | ||
* Use the actionReader and actionHandler to process new blocks. | ||
* | ||
* @param isReplay Set to true to disable Effects from running until caught up with head block. | ||
*/ | ||
@@ -62,2 +133,5 @@ checkForBlocks(isReplay = false) { | ||
while (!headBlockNumber || this.actionReader.currentBlockNumber < headBlockNumber) { | ||
if (this.shouldPause) { | ||
return; | ||
} | ||
const nextBlock = yield this.actionReader.getNextBlock(); | ||
@@ -69,3 +143,3 @@ if (!nextBlock.blockMeta.isNewBlock) { | ||
if (nextBlockNumberNeeded) { | ||
yield this.actionReader.seekToBlock(nextBlockNumberNeeded - 1); | ||
yield this.actionReader.seekToBlock(nextBlockNumberNeeded); | ||
} | ||
@@ -76,3 +150,19 @@ headBlockNumber = this.actionReader.headBlockNumber; | ||
} | ||
get status() { | ||
if (this.clean) { | ||
return interfaces_1.IndexingStatus.Initial; | ||
} | ||
if (this.running && !this.shouldPause) { | ||
return interfaces_1.IndexingStatus.Indexing; | ||
} | ||
if (this.running && this.shouldPause) { | ||
return interfaces_1.IndexingStatus.Pausing; | ||
} | ||
if (this.error) { | ||
return interfaces_1.IndexingStatus.Stopped; | ||
} | ||
return interfaces_1.IndexingStatus.Paused; | ||
} | ||
} | ||
exports.BaseActionWatcher = BaseActionWatcher; | ||
//# sourceMappingURL=BaseActionWatcher.js.map |
@@ -1,4 +0,6 @@ | ||
export { Action, Block, BlockInfo, Effect, HandlerVersion, IndexState, Updater } from "./interfaces"; | ||
export { AbstractActionHandler } from "./AbstractActionHandler"; | ||
export { AbstractActionReader } from "./AbstractActionReader"; | ||
export { BaseActionWatcher } from "./BaseActionWatcher"; | ||
export { AbstractActionHandler } from './AbstractActionHandler'; | ||
export { AbstractActionReader } from './AbstractActionReader'; | ||
export { BaseActionWatcher } from './BaseActionWatcher'; | ||
export { ExpressActionWatcher } from './ExpressActionWatcher'; | ||
export * from './interfaces'; | ||
export * from './errors'; |
"use strict"; | ||
function __export(m) { | ||
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; | ||
} | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -9,1 +12,6 @@ var AbstractActionHandler_1 = require("./AbstractActionHandler"); | ||
exports.BaseActionWatcher = BaseActionWatcher_1.BaseActionWatcher; | ||
var ExpressActionWatcher_1 = require("./ExpressActionWatcher"); | ||
exports.ExpressActionWatcher = ExpressActionWatcher_1.ExpressActionWatcher; | ||
__export(require("./interfaces")); | ||
__export(require("./errors")); | ||
//# sourceMappingURL=index.js.map |
@@ -15,7 +15,2 @@ export interface ActionReaderOptions { | ||
onlyIrreversible?: boolean; | ||
/** | ||
* This determines how many blocks in the past are cached. This is used for determining | ||
* block validity during both normal operation and when rolling back. | ||
*/ | ||
maxHistoryLength?: number; | ||
} | ||
@@ -79,1 +74,26 @@ export interface Block { | ||
} | ||
export interface HandlerInfo { | ||
lastProcessedBlockNumber: number; | ||
lastProcessedBlockHash: string; | ||
handlerVersionName: string; | ||
} | ||
export interface ReaderInfo { | ||
currentBlockNumber: number; | ||
startAtBlock: number; | ||
headBlockNumber: number; | ||
onlyIrreversible: boolean; | ||
lastIrreversibleBlockNumber: number; | ||
} | ||
export declare enum IndexingStatus { | ||
Initial = "initial", | ||
Indexing = "indexing", | ||
Pausing = "pausing", | ||
Paused = "paused", | ||
Stopped = "stopped" | ||
} | ||
export interface DemuxInfo { | ||
indexingStatus: IndexingStatus; | ||
error?: Error; | ||
handler: HandlerInfo; | ||
reader: ReaderInfo; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var IndexingStatus; | ||
(function (IndexingStatus) { | ||
IndexingStatus["Initial"] = "initial"; | ||
IndexingStatus["Indexing"] = "indexing"; | ||
IndexingStatus["Pausing"] = "pausing"; | ||
IndexingStatus["Paused"] = "paused"; | ||
IndexingStatus["Stopped"] = "stopped"; | ||
})(IndexingStatus = exports.IndexingStatus || (exports.IndexingStatus = {})); | ||
//# sourceMappingURL=interfaces.js.map |
{ | ||
"name": "demux", | ||
"version": "3.1.4-fd42365.0", | ||
"version": "4.0.0", | ||
"author": { | ||
@@ -14,11 +14,15 @@ "name": "Julien Heller", | ||
"devDependencies": { | ||
"@blockone/tslint-config-blockone": "^2.0.0", | ||
"@types/bunyan": "^1.8.5", | ||
"@types/express": "^4.16.0", | ||
"@types/jest": "^23.1.4", | ||
"@types/node": "^10.5.1", | ||
"@types/request-promise-native": "^1.0.15", | ||
"@types/supertest": "^2.0.7", | ||
"eslint": "^4.9.0", | ||
"eslint-config-airbnb-base": "12.1.0", | ||
"eslint-plugin-import": "^2.7.0", | ||
"jest": "^22.4.3", | ||
"jest": "^23.6.0", | ||
"release-it": "^7.5.0", | ||
"supertest": "^3.4.1", | ||
"ts-jest": "^23.0.0", | ||
@@ -30,10 +34,13 @@ "tslint": "^5.10.0", | ||
}, | ||
"dependencies": { | ||
"bunyan": "1.8.12", | ||
"express": "4.16.4" | ||
}, | ||
"scripts": { | ||
"build": "tsc", | ||
"compile": "tsc", | ||
"watch": "tsc -w", | ||
"example": "./run-example.sh", | ||
"build": "rm -rf dist/* && tsc", | ||
"build-docs": "./scripts/build-docs.sh", | ||
"build-all": "rm -rf dist/* && tsc && ./scripts/build-docs.sh", | ||
"example": "./scripts/run-example.sh", | ||
"lint": "tslint -c tslint.json -p tsconfig.json", | ||
"test": "jest", | ||
"build-docs": "./build-docs.sh", | ||
"test": "jest --detectOpenHandles --maxWorkers=2", | ||
"current-version": "echo $npm_package_version" | ||
@@ -57,6 +64,3 @@ }, | ||
"testEnvironment": "node" | ||
}, | ||
"dependencies": { | ||
"bunyan": "^1.8.12" | ||
} | ||
} |
@@ -86,2 +86,4 @@ # demux-js [![Build Status](https://travis-ci.org/EOSIO/demux-js.svg?branch=develop)](https://travis-ci.org/EOSIO/demux-js) | ||
* [**`ExpressActionWatcher`**](https://eosio.github.io/demux-js/classes/expressactionwatcher.html): Exposes the API methods from the BaseActionWatcher through an Express server | ||
In order to process actions, we need the following things: | ||
@@ -95,9 +97,46 @@ | ||
- Instantiate the implemented `AbstractActionReader` with any needed configuration | ||
- Instantiate the implemented `AbstractActionHandler`, passing in the `HandlerVersion` and any other needed configuration | ||
- Instantiate the implemented `AbstractActionReader` with any needed configuration | ||
- Instantiate a `BaseActionWatcher`, passing in the above Handler and Reader instances | ||
- Call `watch()` on the Watcher | ||
- Instantiate the `BaseActionWatcher` (or a subclass), passing in the Action Handler and Action Watcher instances | ||
- Start indexing via the Action Watcher's `watch()` method (by either calling it directly or otherwise) | ||
#### Example | ||
```javascript | ||
const { BaseActionWatcher, ExpressActionWatcher } = require("demux") | ||
const { MyActionReader } = require("./MyActionReader") | ||
const { MyActionHandler } = require("./MyActionHandler") | ||
const { handlerVersions } = require("./handlerVersions") | ||
const { readerConfig, handlerConfig, pollInterval, portNumber } = require("./config") | ||
const actionReader = new MyActionReader(readerConfig) | ||
const actioHandler = new MyActionHandler(handlerVersions, handlerConfig) | ||
``` | ||
Then, either | ||
```javascript | ||
const watcher = new BaseActionWatcher( | ||
actionReader, | ||
actionHandler, | ||
pollInterval, | ||
) | ||
watcher.watch() | ||
``` | ||
Or, | ||
```javascript | ||
const expressWatcher = new ExpressActionWatcher( | ||
actionReader, | ||
actionHandler, | ||
pollInterval, | ||
portNumber, | ||
) | ||
expressWatcher.listen() | ||
// You can then make a POST request to `/start` on your configured endpoint | ||
``` | ||
### [**API documentation**](https://eosio.github.io/demux-js/) | ||
### [Learn from a full example](examples/eos-transfers) |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
24
1307
1
141
89262
2
18
+ Addedexpress@4.16.4
+ Addedaccepts@1.3.8(transitive)
+ Addedarray-flatten@1.1.1(transitive)
+ Addedbody-parser@1.18.3(transitive)
+ Addedbunyan@1.8.12(transitive)
+ Addedbytes@3.0.0(transitive)
+ Addedcontent-disposition@0.5.2(transitive)
+ Addedcontent-type@1.0.5(transitive)
+ Addedcookie@0.3.1(transitive)
+ Addedcookie-signature@1.0.6(transitive)
+ Addeddebug@2.6.9(transitive)
+ Addeddepd@1.1.2(transitive)
+ Addeddestroy@1.0.4(transitive)
+ Addedee-first@1.1.1(transitive)
+ Addedencodeurl@1.0.2(transitive)
+ Addedescape-html@1.0.3(transitive)
+ Addedetag@1.8.1(transitive)
+ Addedexpress@4.16.4(transitive)
+ Addedfinalhandler@1.1.1(transitive)
+ Addedforwarded@0.2.0(transitive)
+ Addedfresh@0.5.2(transitive)
+ Addedhttp-errors@1.6.3(transitive)
+ Addediconv-lite@0.4.23(transitive)
+ Addedinherits@2.0.3(transitive)
+ Addedipaddr.js@1.9.1(transitive)
+ Addedmedia-typer@0.3.0(transitive)
+ Addedmerge-descriptors@1.0.1(transitive)
+ Addedmethods@1.1.2(transitive)
+ Addedmime@1.4.1(transitive)
+ Addedmime-db@1.52.0(transitive)
+ Addedmime-types@2.1.35(transitive)
+ Addedms@2.0.0(transitive)
+ Addednegotiator@0.6.3(transitive)
+ Addedon-finished@2.3.0(transitive)
+ Addedparseurl@1.3.3(transitive)
+ Addedpath-to-regexp@0.1.7(transitive)
+ Addedproxy-addr@2.0.7(transitive)
+ Addedqs@6.5.2(transitive)
+ Addedrange-parser@1.2.1(transitive)
+ Addedraw-body@2.3.3(transitive)
+ Addedsafe-buffer@5.1.2(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedsend@0.16.2(transitive)
+ Addedserve-static@1.13.2(transitive)
+ Addedsetprototypeof@1.1.0(transitive)
+ Addedstatuses@1.4.0(transitive)
+ Addedtype-is@1.6.18(transitive)
+ Addedunpipe@1.0.0(transitive)
+ Addedutils-merge@1.0.1(transitive)
+ Addedvary@1.1.2(transitive)
- Removedbunyan@1.8.15(transitive)
- Removedinherits@2.0.4(transitive)
Updatedbunyan@1.8.12