EOS 之demux源码解析
Demux从Facebook的Flux Architecture架构模式和Redux(JavaScript程序的状态容器,即应用数据流框架)中汲取灵感,创建了一个后端基础架构模式。Demux赋予区块链事件溯源技术,可以准确地更新EOSIO上应用程序的可查询数据库。
Demux的一大优势是允许区块链事件自动地(并且可验证地)更新到Mongo或Postgres SQL数据库,这意味着存储在其中的数据仍然可以通过区块链进行验证。并且兼具传统数据库的灵活性和速度,及区块链的信任和不可变属性,达到了两全其美的效果。
如上图所示:
Action Reader 负责读取bloackchain的数据。
Action watcher 负责调度Action Reader检测新的chain数据。
Action Handler 负责过滤和分发updaters 和effects事件。
目前我们项目是在updaters里面更新数据库数据,effects事件的具体作用还没有研究到。
通过example来解读源码
index.js
const {
readers: { eos: { NodeosActionReader } },
watchers: { BaseActionWatcher },
} = require("../../dist/")
const ObjectActionHandler = require("./ObjectActionHandler")
const updaters = require("./updaters")
const effects = require("./effects")
// 设置handler分发的updaters和effects
const actionHandler = new ObjectActionHandler(
updaters,
effects,
)
// 定义reader获取数据地址,读取位置
const actionReader = new NodeosActionReader(
"http://mainnet.eoscalgary.io", // Thanks EOS Calgary!
0, // Start at most recent blocks
true, // 设置是否获取不可逆的数据
)
// 将reader和handler设置到watcher
const actionWatcher = new BaseActionWatcher(
actionReader,
actionHandler,
500,
)
// 开始轮询监控chain数据
actionWatcher.watch()
example里面的代码就不贴了,有兴趣可以自己看看源码。
BaseActionWatcher
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) {
try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) {
try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) {
result.done ? resolve(result.value) : new P(function (resolve) {
resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Cooredinates implementations of `AbstractActionReader`s and `AbstractActionHandler`s in
* a polling loop.
*/
class BaseActionWatcher {
constructor(actionReader, actionHandler, pollInterval) {
this.actionReader = actionReader;
this.actionHandler = actionHandler;
this.pollInterval = pollInterval;
}
/**
* Starts a polling loop running in replay mode.
*/
replay() {
return __awaiter(this, void 0, void 0, function* () {
yield this.actionReader.seekToBlock(this.actionReader.startAtBlock);
yield this.watch();
});
}
/**
* Uses the given actionReader and actionHandler to poll and process new blocks.
*/
watch() {
return __awaiter(this, void 0,