atombeak
Version:
Create asynchronous atomic functions!
96 lines (95 loc) • 3.75 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var Message_1 = require("./Message");
var TransactionState_1 = require("./TransactionState");
var Command_1 = require("./Command");
var Log_1 = require("../Log");
var Trampoline_1 = require("../Trampoline");
var Transaction = /** @class */ (function () {
function Transaction(originalOperation, outer, dispatch) {
this.originalOperation = originalOperation;
this.dispatch = dispatch;
this.messages = [];
this.isExecuting = false;
this.isDone = false;
this.operation = originalOperation;
var attempt = 0;
var log = Log_1.Log.create(outer);
this.state = new TransactionState_1.Pending(attempt, log, []);
this.executeCommand(Command_1.shouldRestart(attempt, log));
}
Transaction.prototype.push = function (message) {
var _this = this;
if (this.isDone) {
return;
}
this.messages = this.messages.concat([message]);
if (!this.isExecuting) {
this.isExecuting = true;
while (this.messages.length > 0) {
var _a = this.messages, head = _a[0], tail = _a.slice(1);
this.messages = tail;
var _b = this.state.next(head), nextState = _b[0], command = _b[1];
this.state = nextState;
this.executeCommand(command);
}
if (this.state instanceof TransactionState_1.Done) {
this.state.getActions().forEach(function (action) {
_this.dispatch(action);
});
this.isDone = true;
}
this.isExecuting = false;
}
};
Transaction.prototype.executeCommand = function (command) {
var _this = this;
if (command.type === Command_1.NO_OP) {
return;
}
else if (command.type === Command_1.RESOLVE) {
// What?
}
else if (command.type === Command_1.SHOULD_RESTART) {
this.operation = this.originalOperation;
var trampoline = this.operation.execute(command.log);
if (trampoline.type === Trampoline_1.ITER) {
trampoline.next().then(function (_a) {
var operation = _a[0], log = _a[1];
_this.operation = operation;
_this.push(Message_1.nextIteration(command.attempt, log));
});
}
else if (trampoline.type === Trampoline_1.DONE) {
this.push(Message_1.resultReceivedMessage(command.attempt, trampoline.value));
}
else {
var exhaustive = trampoline;
throw new Error(exhaustive);
}
}
else if (command.type === Command_1.SHOULD_CONTINUE) {
var trampoline = this.operation.execute(command.log);
if (trampoline.type === Trampoline_1.ITER) {
trampoline.next().then(function (_a) {
var operation = _a[0], log = _a[1];
_this.operation = operation;
_this.push(Message_1.nextIteration(command.attempt, log));
});
}
else if (trampoline.type === Trampoline_1.DONE) {
this.push(Message_1.resultReceivedMessage(command.attempt, trampoline.value));
}
else {
var exhaustive = trampoline;
throw new Error(exhaustive);
}
}
else {
var exhaustive = command;
throw new Error(exhaustive);
}
};
return Transaction;
}());
exports.Transaction = Transaction;