const utils = require('../../pdm-dsu-toolkit/services/utils');
const {INFO_PATH, LOG_PATH, EXTRA_INFO_PATH} = require('../constants');
const Status = require('../model/Status');
/**
* @param {string} domain: anchoring domain. defaults to 'default'
* @param {strategy} strategy
* @function BatchService
* @memberOf Services
*/
function StatusService(domain, strategy){
const strategies = require("../../pdm-dsu-toolkit/services/strategy");
const OrderStatus = require('../model').OrderStatus;
const endpoint = 'status';
domain = domain || "default";
let isSimple = strategies.SIMPLE === (strategy || strategies.SIMPLE);
let selectMethod = function(templateKeySSI){
if (templateKeySSI.getTypeName() === 'array')
return utils.getResolver().createDSUForExistingSSI;
return utils.getResolver().createDSU;
}
let createLog = function(id, prevStatus, status, timestamp){
const ts = timestamp ? timestamp : Date.now();
return prevStatus
? `${id} ${ts} updated status from ${prevStatus.status || prevStatus} to ${status.status || status}`
: `${id} ${ts} set status to ${status.status || status}`;
}
const createExtraInfo = function (id, extraInfo, timestamp) {
return `${id} ${timestamp ? timestamp : Date.now()} ${extraInfo ? extraInfo : ''}`
}
/**
* Resolves the DSU and loads the status object with all its properties, mutable or not
* @param {KeySSI} keySSI
* @param {function(err, Status, Archive)} callback
*/
this.get = function(keySSI, callback){
utils.getResolver().loadDSU(keySSI, (err, dsu) => {
if (err)
return callback(err);
dsu.readFile(INFO_PATH, (err, data) => {
if (err)
return callback(err);
let status;
try{
status = JSON.parse(data);
} catch (e){
return callback(`Could not parse status in DSU ${keySSI.getIdentifier()}`);
}
// console.log('@@ StatusService.get status=', status);
dsu.readFile(LOG_PATH, (err, log) => {
if (err)
return callback(err);
try {
log = JSON.parse(log);
// console.log('@@ StatusService.get log=', log);
} catch (e){
return callback(e);
}
if (!Array.isArray(log))
return callback(`Invalid log data`);
const returnFunc = function(extraInfo){
const _status = new Status({
status: status,
log: log,
extraInfo: extraInfo
});
return callback(undefined, _status, dsu);
}
dsu.readFile(EXTRA_INFO_PATH, (err, extraInfo) => {
if (err || !extraInfo)
return returnFunc();
try{
extraInfo = JSON.parse(extraInfo);
} catch(e){
return callback(e);
}
returnFunc(extraInfo);
});
});
});
});
}
const createStatus = function(status, id, oldStatus){
let log = createLog(id, oldStatus, status);
return new Status({
status: status,
log: [log]
});
}
const parseStatus = function(status, id, oldStatus){
if (typeof status === 'string')
return createStatus(status, id, oldStatus);
if (status instanceof Status)
return status;
return new Status(status);
}
/**
* Creates aC Status DSU
* @param {OrderStatus|ShipmentStatus|Status} status
* @param {String} id the sender id
* @param {function} callback
* @return {string} keySSI
*/
this.create = function(status, id, callback){
if (!callback){
callback = id;
id = undefined
} else {
status = parseStatus(status, id);
}
if (isSimple){
let keyGenFunction = require('../commands/setStatusSSI').createStatusSSI;
let keySSI = keyGenFunction(status, domain);
selectMethod(keySSI)(keySSI, (err, dsu) => {
if (err)
return callback(err);
const cb = function(err, ...results){
if (err)
return dsu.cancelBatch(err2 => {
callback(err);
});
callback(undefined, ...results);
}
try {
dsu.beginBatch();
} catch (e) {
return callback(e);
}
dsu.writeFile(INFO_PATH, JSON.stringify(status.status), (err) => {
if (err)
return cb(err);
const returnFunc = function(err){
if (err)
return cb(err);
dsu.commitBatch((err) => {
if (err)
return cb(err);
dsu.getKeySSIAsObject(callback);
});
}
dsu.writeFile(LOG_PATH, JSON.stringify(status.log), returnFunc);
});
});
} else {
return callback(`Not implemented`);
}
};
this.update = function(keySSI, status, id, callback){
if (!callback){
callback = id;
id = undefined
} else {
status = parseStatus(status, id);
}
if (isSimple){
keySSI = utils.getKeySSISpace().parse(keySSI);
utils.getResolver().loadDSU(keySSI.getIdentifier(), {skipCache: true}, (err, dsu) => {
if (err)
return callback(err);
dsu.readFile(INFO_PATH, (err, prevStatus) => {
if (err)
return callback(err);
try{
prevStatus = JSON.parse(prevStatus);
} catch (e){
return callback(e);
}
status = parseStatus(status, id, prevStatus);
let stringified;
try{
stringified = JSON.stringify(status.status);
} catch (e){
return callback(e);
}
const cb = function(err, ...results){
if (err)
return dsu.cancelBatch(err2 => {
callback(err);
});
callback(undefined, ...results);
}
try {
dsu.beginBatch();
} catch (e) {
return callback(e);
}
dsu.writeFile(INFO_PATH, stringified, (err) => {
if (err)
return cb(err);
const returnFunc = function(err){
if (err)
return cb(err);
dsu.commitBatch((err) => {
if (err)
return cb(err);
dsu.getKeySSIAsObject(callback);
});
}
const timestamp = Date.now()
let log = createLog(id, prevStatus, status, timestamp);
dsu.readFile(LOG_PATH, (err, data) => {
if (err)
return cb(err);
try {
data = JSON.parse(data);
} catch (e){
return cb(e);
}
if (!Array.isArray(data))
return cb(`Invalid data Types`);
dsu.writeFile(LOG_PATH, JSON.stringify([...data, log]), (err) => {
if (err)
return cb(err);
dsu.readFile(EXTRA_INFO_PATH, (err, extraInfo) => {
if (err)
extraInfo = {};
else {
try {
extraInfo = JSON.parse(extraInfo);
} catch (e){
return cb(err);
}
}
if (!status.extraInfo)
return returnFunc();
if (typeof status.extraInfo === 'object') {
const extraInfoStatusArray = status.extraInfo[status.status];
const lastElement = extraInfoStatusArray === undefined ? '' : extraInfoStatusArray.pop();
if (extraInfo[status.status])
extraInfo[status.status].push(createExtraInfo(id, lastElement, timestamp))
else
extraInfo[status.status] = [createExtraInfo(id, lastElement, timestamp)];
} else if (extraInfo.hasOwnProperty(status.status)) {
extraInfo[status.status].push(createExtraInfo(id, status.extraInfo, timestamp))
} else {
extraInfo[status.status] = [createExtraInfo(id, status.extraInfo, timestamp)]
}
dsu.writeFile(EXTRA_INFO_PATH, JSON.stringify(extraInfo), returnFunc);
});
});
});
});
});
});
} else {
return callback(`Not implemented`);
}
}
}
module.exports = StatusService;
Source