Skip to content
Snippets Groups Projects
Commit c1563c62 authored by Cédric Moreau's avatar Cédric Moreau
Browse files

[enh] Speed up "members"

parent fcd516b5
No related branches found
No related tags found
No related merge requests found
import {Server} from 'duniter/server'
export class DataFinder {
private memCache: {
[cacheName: string]: {
[k: string]: any
}
} = {}
constructor(protected duniterServer: Server) {
}
findPendingMembers() {
return this.query('SELECT `buid`,`pubkey`,`uid`,`hash`,`expires_on`,`revocation_sig` FROM identities_pending WHERE `member`=0')
}
findPendingCertsToTarget(toPubkey: string, hash: string) {
return this.getFromCacheOrDB('findPendingCertsToTarget', [toPubkey, hash].join('-'), () => this.query(
'SELECT `from`,`block_number`,`block_hash`,`expires_on` FROM certifications_pending WHERE `to`=\''+toPubkey+'\' AND `target`=\''+hash+'\' ORDER BY `expires_on` DESC'))
}
getWotexInfos(uid: string) {
return this.duniterServer.dal.idtyDAL.query('' +
'SELECT hash, uid, pub, wotb_id FROM i_index WHERE uid = ? ' +
'UNION ALL ' + 'SELECT hash, uid, pubkey as pub, (SELECT NULL) AS wotb_id FROM idty WHERE uid = ?', [uid, uid])
}
async getBlockMedianTimeAndHash(block_number: number): Promise<{ hash: string, medianTime: number }|undefined> {
return (await this.getFromCacheOrDB('getBlockMedianTimeAndHash', String(block_number),() => this.duniterServer.dal.getBlock(block_number))) || undefined
}
getUidOfPub(pub: string): Promise<{ uid: string }[]> {
return this.getFromCacheOrDB('getUidOfPub', pub, () => this.query('SELECT `uid` FROM i_index WHERE `pub`=\''+pub+'\' LIMIT 1'))
}
async getWotbIdByIssuerPubkey(issuerPubkey: string) {
return this.getFromCacheOrDB('getWotbIdByIssuerPubkey', issuerPubkey, async () => (await this.duniterServer.dal.iindexDAL.query('SELECT wotb_id FROM i_index WHERE pub = ? AND wotb_id IS NOT NULL', [issuerPubkey]))[0].wotb_id)
}
getChainableOnByIssuerPubkey(issuerPubkey: string) {
return this.query('SELECT `chainable_on` FROM c_index WHERE `issuer`=\''+issuerPubkey+'\' ORDER BY `chainable_on` DESC LIMIT 1')
}
getChainableOnByIssuerPubkeyByExpOn(from: string) {
return this.getFromCacheOrDB('getChainableOnByIssuerPubkeyByExpOn', from, () => this.query('SELECT `chainable_on` FROM c_index WHERE `issuer`=\''+from+'\' ORDER BY `expires_on` DESC LIMIT 1'))
}
getCurrentBlockOrNull() {
return this.duniterServer.dal.getCurrentBlockOrNull()
}
findCertsOfIssuer(pub: string, tmpOrder: string) {
return this.getFromCacheOrDB('findCertsOfIssuer', [pub, tmpOrder].join('-'), () => this.query(
'SELECT `receiver`,`written_on`,`expires_on` FROM c_index WHERE `issuer`=\''+pub+'\' ORDER BY `expires_on` '+tmpOrder))
}
findCertsOfReceiver(pub: any, tmpOrder: string) {
return this.getFromCacheOrDB('findCertsOfReceiver', [pub, tmpOrder].join('-'), () => this.query(
'SELECT `issuer`,`written_on`,`expires_on` FROM c_index WHERE `receiver`=\''+pub+'\' ORDER BY `expires_on` '+tmpOrder))
}
getProtagonist(pub: string) {
return this.getFromCacheOrDB('getProtagonist', pub, () => this.query('SELECT `uid`,`wotb_id` FROM i_index WHERE `pub`=\''+pub+'\' LIMIT 1'))
}
getCertsPending(pub: string, tmpOrder: string) {
return this.getFromCacheOrDB('getCertsPending', [pub, tmpOrder].join('-'), () => this.query(
'SELECT `from`,`to`,`block_number`,`expires_on` FROM certifications_pending WHERE `from`=\''+pub+'\' ORDER BY `expires_on` '+tmpOrder))
}
getCertsPendingFromTo(pub: any, tmpOrder: string) {
return this.getFromCacheOrDB('getCertsPendingFromTo', [pub, tmpOrder].join('-'), () => this.query(
'SELECT `from`,`block_number`,`block_hash`,`expires_on` FROM certifications_pending WHERE `to`=\''+pub+'\' ORDER BY `expires_on` '+tmpOrder))
}
getMembers() {
return this.getFromCacheOrDB('getMembers', 'members', () => this.query('SELECT `uid`,`pub`,`member`,`written_on`,`wotb_id` FROM i_index WHERE `member`=1'))
}
membershipWrittenOnExpiresOn(pub: string) {
return this.getFromCacheOrDB('membershipWrittenOnExpiresOn', pub, () => this.query(
'SELECT `written_on`,`expires_on` FROM m_index WHERE `pub`=\''+pub+'\' ORDER BY `expires_on` DESC LIMIT 1'))
}
query(sql: string, params?: any[]) {
return this.duniterServer.dal.peerDAL.query(sql, params || [])
}
async getFromCacheOrDB<T>(cacheName: string, key: string, fetcher: () => Promise<T>) {
const cache = this.memCache[cacheName] || (this.memCache[cacheName] = {})
if (cache[key]) {
return cache[key]
}
return cache[key] = await fetcher()
}
invalidateCache() {
this.memCache = {}
}
}
...@@ -68,7 +68,7 @@ app.get('/willMembers', // chemin (endpoint) ...@@ -68,7 +68,7 @@ app.get('/willMembers', // chemin (endpoint)
* Lister les membres * Lister les membres
***************************************/ ***************************************/
app.get('/members', app.get('/members',
require(__dirname + '/members.js'), require(__dirname + '/members2.js'),
(req, res)=> res.render('members.html', { (req, res)=> res.render('members.html', {
printMenu, printMenu,
help: req.query.help, help: req.query.help,
......
"use strict"; import {DataFinder} from '../lib/DataFinder'
const co = require('co')
const constants = require(__dirname + '/../lib/constants') const constants = require(__dirname + '/../lib/constants')
const randomInt = require(__dirname + '/../lib/randomInt') const randomInt = require(__dirname + '/../lib/randomInt')
const timestampToDatetime = require(__dirname + '/../lib/timestampToDatetime') const timestampToDatetime = require(__dirname + '/../lib/timestampToDatetime')
const membersQuality = require(__dirname + '/tools/membersQuality') const membersQuality = require(__dirname + '/tools/membersQuality')
...@@ -11,22 +8,22 @@ const membersQuality = require(__dirname + '/tools/membersQuality') ...@@ -11,22 +8,22 @@ const membersQuality = require(__dirname + '/tools/membersQuality')
// Préserver les résultats en cache // Préserver les résultats en cache
var lockMembers = false; var lockMembers = false;
var membersLastUptime = 0; var membersLastUptime = 0;
var previousMode = null; var previousMode: any = null;
var previousCentrality = null; var previousCentrality: any = null;
var previousNextYn = "no"; var previousNextYn = "no";
var previousRandomList = "no" var previousRandomList = "no"
var previousRandomCounts = 10 var previousRandomCounts = 10
var membersList = []; var membersList: any[] = [];
var membersIdentity = []; var membersIdentity: any[] = [];
var membersFirstCertifExpire = []; var membersFirstCertifExpire: any[] = [];
var membersCertifsList = []; var membersCertifsList: any[] = [];
var membersPendingCertifsList = []; var membersPendingCertifsList: any[] = [];
var membershipsTimeList = []; var membershipsTimeList: { medianTime: number }[] = [];
var membershipsBlockNumberList = []; var membershipsBlockNumberList: any[] = [];
var membershipsExpireTimeList = []; var membershipsExpireTimeList: any[] = [];
var nbMaxCertifs = 0; var nbMaxCertifs = 0;
var sentries = []; var sentries = [];
var sentriesIndex = []; var sentriesIndex: { [k: string]: boolean } = {};
var countSentries = 0; var countSentries = 0;
/*var meanSentriesReachedBySentriesInSingleExtCert = 0; /*var meanSentriesReachedBySentriesInSingleExtCert = 0;
var meanMembersReachedBySentriesInSingleExtCert = 0; var meanMembersReachedBySentriesInSingleExtCert = 0;
...@@ -38,20 +35,22 @@ var proportionMembersWithQualityUpper1IfNoSentries = 0; ...@@ -38,20 +35,22 @@ var proportionMembersWithQualityUpper1IfNoSentries = 0;
// wotCentrality cache // wotCentrality cache
var lockCentralityCalc = false; var lockCentralityCalc = false;
var membersLastCentralityCalcTime = 0; var membersLastCentralityCalcTime = 0;
var membersCentrality = []; var membersCentrality: any[] = [];
var meanCentrality = 0; var meanCentrality = 0;
var meanShortestsPathLength = 0; var meanShortestsPathLength = 0;
var nbShortestsPath = 0; var nbShortestsPath = 0;
module.exports = (req, res, next) => co(function *() { module.exports = async (req: any, res: any, next: any) => {
var { duniterServer } = req.app.locals var { duniterServer } = req.app.locals
const dataFinder = new DataFinder(duniterServer)
try { try {
// Initaliser les constantes // Initaliser les constantes
const conf = duniterServer.conf; const conf = duniterServer.conf;
const head = yield duniterServer.dal.getCurrentBlockOrNull(); const head = await duniterServer.dal.getCurrentBlockOrNull();
const currentBlockchainTimestamp = head ? head.medianTime : 0; const currentBlockchainTimestamp = head ? head.medianTime : 0;
const membersCount = head ? head.membersCount : 0; const membersCount = head ? head.membersCount : 0;
var dSen = Math.ceil(Math.pow(membersCount, 1 / conf.stepMax)); var dSen = Math.ceil(Math.pow(membersCount, 1 / conf.stepMax));
...@@ -70,9 +69,9 @@ module.exports = (req, res, next) => co(function *() { ...@@ -70,9 +69,9 @@ module.exports = (req, res, next) => co(function *() {
var pendingSigs = req.query.pendingSigs || "no"; // Valeur par défaut var pendingSigs = req.query.pendingSigs || "no"; // Valeur par défaut
var centrality = req.query.centrality || "no"; // Valeur par défaut var centrality = req.query.centrality || "no"; // Valeur par défaut
var format = req.query.format || 'HTML'; // Valeur par défaut var format = req.query.format || 'HTML'; // Valeur par défaut
const nextYn = (req.query.nextYn=="yes") ? "yes":"no"; let nextYn = (req.query.nextYn=="yes") ? "yes":"no";
const randomList = (req.query.randomList=="yes") ? "yes":"no"; let randomList = (req.query.randomList=="yes") ? "yes":"no";
const numberOfRandomMembers = req.query.randomCounts || 10 let numberOfRandomMembers = req.query.randomCounts || 10
// Vérifier la valeur de nextYn dans le cache // Vérifier la valeur de nextYn dans le cache
let lastUpgradeTimeDatas = membersQuality(constants.QUALITY_CACHE_ACTION.INIT); let lastUpgradeTimeDatas = membersQuality(constants.QUALITY_CACHE_ACTION.INIT);
...@@ -116,6 +115,7 @@ module.exports = (req, res, next) => co(function *() { ...@@ -116,6 +115,7 @@ module.exports = (req, res, next) => co(function *() {
if (reinitCache) if (reinitCache)
{ {
// Réinitialiser le cache // Réinitialiser le cache
dataFinder.invalidateCache()
membersLastUptime = Math.floor(Date.now() / 1000); membersLastUptime = Math.floor(Date.now() / 1000);
previousMode = mode; previousMode = mode;
previousCentrality = centrality; previousCentrality = centrality;
...@@ -132,7 +132,7 @@ module.exports = (req, res, next) => co(function *() { ...@@ -132,7 +132,7 @@ module.exports = (req, res, next) => co(function *() {
membershipsExpireTimeList = []; membershipsExpireTimeList = [];
nbMaxCertifs = 0; nbMaxCertifs = 0;
sentries = []; sentries = [];
sentriesIndex = []; sentriesIndex = {};
countSentries = 0; countSentries = 0;
/*meanSentriesReachedBySentriesInSingleExtCert = 0; /*meanSentriesReachedBySentriesInSingleExtCert = 0;
meanMembersReachedBySentriesInSingleExtCert = 0; meanMembersReachedBySentriesInSingleExtCert = 0;
...@@ -161,7 +161,7 @@ module.exports = (req, res, next) => co(function *() { ...@@ -161,7 +161,7 @@ module.exports = (req, res, next) => co(function *() {
sentries = wotbInstance.getSentries(dSen); sentries = wotbInstance.getSentries(dSen);
// Récupérer la liste des identités ayant actuellement le statut de membre // Récupérer la liste des identités ayant actuellement le statut de membre
membersList = yield duniterServer.dal.peerDAL.query('SELECT `uid`,`pub`,`member`,`written_on`,`wotb_id` FROM i_index WHERE `member`=1'); membersList = await dataFinder.getMembers()
if (randomList == "yes") { if (randomList == "yes") {
// Tirer au sort randomCounts membres // Tirer au sort randomCounts membres
...@@ -181,8 +181,7 @@ module.exports = (req, res, next) => co(function *() { ...@@ -181,8 +181,7 @@ module.exports = (req, res, next) => co(function *() {
for (let m=0;m<membersList.length;m++) for (let m=0;m<membersList.length;m++)
{ {
// Récupérer les blockstamp d'écriture et date d'expiration du membership courant du membre m // Récupérer les blockstamp d'écriture et date d'expiration du membership courant du membre m
let tmpQueryResult = yield duniterServer.dal.peerDAL.query( let tmpQueryResult = await dataFinder.membershipWrittenOnExpiresOn(membersList[m].pub);
'SELECT `written_on`,`expires_on` FROM m_index WHERE `pub`=\''+membersList[m].pub+'\' ORDER BY `expires_on` DESC LIMIT 1');
membershipsExpireTimeList.push(tmpQueryResult[0].expires_on); membershipsExpireTimeList.push(tmpQueryResult[0].expires_on);
// Extraire le numéro de bloc du blockstamp d'écriture du membership courant // Extraire le numéro de bloc du blockstamp d'écriture du membership courant
...@@ -193,8 +192,7 @@ module.exports = (req, res, next) => co(function *() { ...@@ -193,8 +192,7 @@ module.exports = (req, res, next) => co(function *() {
let blockstampIdtyWritten = membersList[m].written_on.split("-"); // Separate blockNumber and blockHash let blockstampIdtyWritten = membersList[m].written_on.split("-"); // Separate blockNumber and blockHash
// Récupérer le champ medianTime du bloc d'écriture de l'identité du membre // Récupérer le champ medianTime du bloc d'écriture de l'identité du membre
let resultQueryTimeWrittenIdty = yield duniterServer.dal.peerDAL.query( let resultQueryTimeWrittenIdty = await dataFinder.getBlockMedianTimeAndHash(blockstampIdtyWritten[0])
'SELECT `medianTime` FROM block WHERE `number`=\''+blockstampIdtyWritten[0]+'\' LIMIT 1')
// Vérifier si le membre est référent // Vérifier si le membre est référent
let currentMemberIsSentry = false; let currentMemberIsSentry = false;
...@@ -248,7 +246,7 @@ module.exports = (req, res, next) => co(function *() { ...@@ -248,7 +246,7 @@ module.exports = (req, res, next) => co(function *() {
// Stocker les informations de l'identité // Stocker les informations de l'identité
membersIdentity.push({ membersIdentity.push({
writtenBloc: blockstampIdtyWritten[0], writtenBloc: blockstampIdtyWritten[0],
writtenTimestamp: resultQueryTimeWrittenIdty[0].medianTime, writtenTimestamp: (resultQueryTimeWrittenIdty as any).medianTime,
detailedDistance: detailedDistance, detailedDistance: detailedDistance,
isSentry: currentMemberIsSentry isSentry: currentMemberIsSentry
}); });
...@@ -258,13 +256,11 @@ module.exports = (req, res, next) => co(function *() { ...@@ -258,13 +256,11 @@ module.exports = (req, res, next) => co(function *() {
let tmpOrder = (sort_by == "lastSig") ? 'DESC' : 'ASC'; let tmpOrder = (sort_by == "lastSig") ? 'DESC' : 'ASC';
if (mode == 'emitted') if (mode == 'emitted')
{ {
tmpQueryCertifsList = yield duniterServer.dal.peerDAL.query( tmpQueryCertifsList = await dataFinder.findCertsOfIssuer(membersList[m].pub, tmpOrder)
'SELECT `receiver`,`written_on`,`expires_on` FROM c_index WHERE `issuer`=\''+membersList[m].pub+'\' ORDER BY `expires_on` '+tmpOrder);
} }
else else
{ {
tmpQueryCertifsList = yield duniterServer.dal.peerDAL.query( tmpQueryCertifsList = await dataFinder.findCertsOfReceiver(membersList[m].pub, tmpOrder)
'SELECT `issuer`,`written_on`,`expires_on` FROM c_index WHERE `receiver`=\''+membersList[m].pub+'\' ORDER BY `expires_on` '+tmpOrder);
} }
// Calculer le nombre de certifications reçus/émises par le membre courant // Calculer le nombre de certifications reçus/émises par le membre courant
...@@ -278,11 +274,11 @@ module.exports = (req, res, next) => co(function *() { ...@@ -278,11 +274,11 @@ module.exports = (req, res, next) => co(function *() {
let tmpQueryGetUidProtagonistCert let tmpQueryGetUidProtagonistCert
if (mode == 'emitted') if (mode == 'emitted')
{ {
tmpQueryGetUidProtagonistCert = yield duniterServer.dal.peerDAL.query('SELECT `uid`,`wotb_id` FROM i_index WHERE `pub`=\''+tmpQueryCertifsList[i].receiver+'\' LIMIT 1'); tmpQueryGetUidProtagonistCert = await dataFinder.getProtagonist(tmpQueryCertifsList[i].receiver)
} }
else else
{ {
tmpQueryGetUidProtagonistCert = yield duniterServer.dal.peerDAL.query('SELECT `uid`,`wotb_id` FROM i_index WHERE `pub`=\''+tmpQueryCertifsList[i].issuer+'\' LIMIT 1'); tmpQueryGetUidProtagonistCert = await dataFinder.getProtagonist(tmpQueryCertifsList[i].issuer)
} }
let tmpBlockWrittenOn = tmpQueryCertifsList[i].written_on.split("-"); let tmpBlockWrittenOn = tmpQueryCertifsList[i].written_on.split("-");
...@@ -308,13 +304,11 @@ module.exports = (req, res, next) => co(function *() { ...@@ -308,13 +304,11 @@ module.exports = (req, res, next) => co(function *() {
let tmpQueryPendingCertifsList = []; let tmpQueryPendingCertifsList = [];
if (mode == 'emitted') if (mode == 'emitted')
{ {
tmpQueryPendingCertifsList = yield duniterServer.dal.peerDAL.query( tmpQueryPendingCertifsList = await dataFinder.getCertsPending(membersList[m].pub, tmpOrder)
'SELECT `from`,`to`,`block_number`,`expires_on` FROM certifications_pending WHERE `from`=\''+membersList[m].pub+'\' ORDER BY `expires_on` '+tmpOrder);
} }
else else
{ {
tmpQueryPendingCertifsList = yield duniterServer.dal.peerDAL.query( tmpQueryPendingCertifsList = await dataFinder.getCertsPendingFromTo(membersList[m].pub, tmpOrder)
'SELECT `from`,`block_number`,`block_hash`,`expires_on` FROM certifications_pending WHERE `to`=\''+membersList[m].pub+'\' ORDER BY `expires_on` '+tmpOrder);
} }
// Récupérer les uid des émetteurs des certifications reçus par l'utilisateur // Récupérer les uid des émetteurs des certifications reçus par l'utilisateur
...@@ -323,17 +317,17 @@ module.exports = (req, res, next) => co(function *() { ...@@ -323,17 +317,17 @@ module.exports = (req, res, next) => co(function *() {
for (var i=0;i<tmpQueryPendingCertifsList.length;i++) for (var i=0;i<tmpQueryPendingCertifsList.length;i++)
{ {
// Récupérer le medianTime et le hash du bloc d'émission de la certification // Récupérer le medianTime et le hash du bloc d'émission de la certification
let emittedBlock = yield duniterServer.dal.peerDAL.query('SELECT `hash`,`medianTime` FROM block WHERE `number`=\''+tmpQueryPendingCertifsList[i].block_number+'\' AND `fork`=0 LIMIT 1'); let emittedBlock = await dataFinder.getBlockMedianTimeAndHash(tmpQueryPendingCertifsList[i].block_number)
let tmpPub = (mode=='emitted') ? tmpQueryPendingCertifsList[i].to:tmpQueryPendingCertifsList[i].from; let tmpPub = (mode=='emitted') ? tmpQueryPendingCertifsList[i].to:tmpQueryPendingCertifsList[i].from;
let tmpQueryGetUidProtagonistPendingCert = yield duniterServer.dal.peerDAL.query('SELECT `uid` FROM i_index WHERE `pub`=\''+tmpPub+'\' LIMIT 1'); let tmpQueryGetUidProtagonistPendingCert = await dataFinder.getUidOfPub(tmpPub)
// Vérifier que l'émetteur de la certification correspond à une identié connue // Vérifier que l'émetteur de la certification correspond à une identié connue
if ( tmpQueryGetUidProtagonistPendingCert.length > 0 ) if ( tmpQueryGetUidProtagonistPendingCert.length > 0 )
{ {
// Vérifier la validité du blockStamp de la certification en piscine // Vérifier la validité du blockStamp de la certification en piscine
let validBlockStamp = false; let validBlockStamp = false;
if (typeof(emittedBlock[0]) != 'undefined' && emittedBlock[0].hash == tmpQueryPendingCertifsList[i].block_hash) if (typeof(emittedBlock) != 'undefined' && emittedBlock.hash == tmpQueryPendingCertifsList[i].block_hash)
{ validBlockStamp = true; } { validBlockStamp = true; }
// Vérifier que le membre courant n'a pas déjà émis/reçu d'autre(s) certification(s) vis à vis du même protagoniste ET dans le même état de validité du blockstamp // Vérifier que le membre courant n'a pas déjà émis/reçu d'autre(s) certification(s) vis à vis du même protagoniste ET dans le même état de validité du blockstamp
...@@ -348,7 +342,7 @@ module.exports = (req, res, next) => co(function *() { ...@@ -348,7 +342,7 @@ module.exports = (req, res, next) => co(function *() {
if (!doubloonPendingCertif) if (!doubloonPendingCertif)
{ {
// récupérer le timestamp d'écriture de la dernière certification écrite par l'émetteur // récupérer le timestamp d'écriture de la dernière certification écrite par l'émetteur
let tmpQueryLastIssuerCert = yield duniterServer.dal.peerDAL.query('SELECT `chainable_on` FROM c_index WHERE `issuer`=\''+tmpQueryPendingCertifsList[i].from+'\' ORDER BY `expires_on` DESC LIMIT 1'); let tmpQueryLastIssuerCert = await dataFinder.getChainableOnByIssuerPubkeyByExpOn(tmpQueryPendingCertifsList[i].from)
// Stoker la liste des certifications en piscine qui n'ont pas encore expirées // Stoker la liste des certifications en piscine qui n'ont pas encore expirées
if (tmpQueryPendingCertifsList[i].expires_on > currentBlockchainTimestamp) if (tmpQueryPendingCertifsList[i].expires_on > currentBlockchainTimestamp)
...@@ -376,8 +370,7 @@ module.exports = (req, res, next) => co(function *() { ...@@ -376,8 +370,7 @@ module.exports = (req, res, next) => co(function *() {
// Convertir chaque blockNumber (de membership) en timestamp // Convertir chaque blockNumber (de membership) en timestamp
for (const membershipBlockNumber of membershipsBlockNumberList) for (const membershipBlockNumber of membershipsBlockNumberList)
{ {
membershipsTimeList.push(yield duniterServer.dal.peerDAL.query( membershipsTimeList.push(await dataFinder.getBlockMedianTimeAndHash(membershipBlockNumber) as { medianTime: number })
'SELECT `medianTime` FROM block WHERE `number`=\''+membershipBlockNumber+'\' LIMIT 1') );
} }
// Traiter les cas ou expires_on est indéfini // Traiter les cas ou expires_on est indéfini
...@@ -385,7 +378,7 @@ module.exports = (req, res, next) => co(function *() { ...@@ -385,7 +378,7 @@ module.exports = (req, res, next) => co(function *() {
{ {
if (membershipsExpireTimeList[i] == null) if (membershipsExpireTimeList[i] == null)
{ {
membershipsExpireTimeList[i] = membershipsTimeList[i] + msValidity; // membershipsExpireTimeList[i] = membershipsTimeList[i] + msValidity; ## msValidity is unknown var?
} }
} }
...@@ -456,7 +449,7 @@ module.exports = (req, res, next) => co(function *() { ...@@ -456,7 +449,7 @@ module.exports = (req, res, next) => co(function *() {
else if (sort_by == "lastRenewal") else if (sort_by == "lastRenewal")
{ {
for (const membershipTimeList of membershipsTimeList) for (const membershipTimeList of membershipsTimeList)
{ tabSort.push(membershipTimeList[0].medianTime); } { tabSort.push(membershipTimeList.medianTime); }
} }
else if (sort_by == "oldestSig" || sort_by == "lastSig") else if (sort_by == "oldestSig" || sort_by == "lastSig")
{ {
...@@ -524,7 +517,7 @@ module.exports = (req, res, next) => co(function *() { ...@@ -524,7 +517,7 @@ module.exports = (req, res, next) => co(function *() {
pub: membersList[idMaxTime].pub, pub: membersList[idMaxTime].pub,
idtyWrittenTimestamp: membersIdentity[idMaxTime].writtenTimestamp, idtyWrittenTimestamp: membersIdentity[idMaxTime].writtenTimestamp,
idtyWrittenBloc: membersIdentity[idMaxTime].writtenBloc, idtyWrittenBloc: membersIdentity[idMaxTime].writtenBloc,
lastRenewalTimestamp: membershipsTimeList[idMaxTime][0].medianTime, lastRenewalTimestamp: membershipsTimeList[idMaxTime].medianTime,
lastRenewalWrittenBloc: membershipsBlockNumberList[idMaxTime], lastRenewalWrittenBloc: membershipsBlockNumberList[idMaxTime],
expireMembershipTimestamp: membershipsExpireTimeList[idMaxTime], expireMembershipTimestamp: membershipsExpireTimeList[idMaxTime],
certifications: membersCertifsList[idMaxTime], certifications: membersCertifsList[idMaxTime],
...@@ -624,11 +617,11 @@ module.exports = (req, res, next) => co(function *() { ...@@ -624,11 +617,11 @@ module.exports = (req, res, next) => co(function *() {
// Template helpers // Template helpers
timestampToDatetime, timestampToDatetime,
// Calculer la proportion de temps restant avant l'expiration // Calculer la proportion de temps restant avant l'expiration
color: function( timestamp, idtyWindow, max ) color: function( timestamp: number, idtyWindow: number, max: number )
{ {
let proportion = ((timestamp-currentBlockchainTimestamp)*max)/idtyWindow; let proportion = ((timestamp-currentBlockchainTimestamp)*max)/idtyWindow;
proportion = proportion < 0 ? 0 : proportion > max ? max : proportion proportion = proportion < 0 ? 0 : proportion > max ? max : proportion
let hex = parseInt( proportion ).toString(16) let hex = proportion.toString(16)
return `#${hex}${hex}${hex}` return `#${hex}${hex}${hex}`
}, },
/** /**
...@@ -636,7 +629,7 @@ module.exports = (req, res, next) => co(function *() { ...@@ -636,7 +629,7 @@ module.exports = (req, res, next) => co(function *() {
* background: hsl( 0, 0%, ${proportion(item.time,period,0,200)}, 1 ) * background: hsl( 0, 0%, ${proportion(item.time,period,0,200)}, 1 )
* background: #${proportion()}${proportion()}${proportion()} * background: #${proportion()}${proportion()}${proportion()}
*/ */
proportion: function( timestamp, maxRange, min, max ) proportion: function( timestamp: number, maxRange: number, min: number, max: number )
{ {
let proportion = ( (timestamp-currentBlockchainTimestamp) * max ) / maxRange let proportion = ( (timestamp-currentBlockchainTimestamp) * max ) / maxRange
proportion = proportion < 0 ? 0 : proportion > max ? max : proportion proportion = proportion < 0 ? 0 : proportion > max ? max : proportion
...@@ -667,4 +660,4 @@ module.exports = (req, res, next) => co(function *() { ...@@ -667,4 +660,4 @@ module.exports = (req, res, next) => co(function *() {
res.status(500).send(`<pre>${e.stack || e.message}</pre>`) res.status(500).send(`<pre>${e.stack || e.message}</pre>`)
} }
}) }
\ No newline at end of file
import {Server} from 'duniter/server' import {Server} from 'duniter/server'
import {DBMembership} from 'duniter/app/lib/dal/sqliteDAL/MembershipDAL' import {DBMembership} from 'duniter/app/lib/dal/sqliteDAL/MembershipDAL'
import {DBIdentity} from 'duniter/app/lib/dal/sqliteDAL/IdentityDAL' import {DBIdentity} from 'duniter/app/lib/dal/sqliteDAL/IdentityDAL'
import {MonitorExecutionTime, showExecutionTimes} from '../lib/MonitorExecutionTime' import {showExecutionTimes} from '../lib/MonitorExecutionTime'
import {DataFinder} from '../lib/DataFinder'
const constants = require(__dirname + '/../lib/constants') const constants = require(__dirname + '/../lib/constants')
const timestampToDatetime = require(__dirname + '/../lib/timestampToDatetime') const timestampToDatetime = require(__dirname + '/../lib/timestampToDatetime')
...@@ -562,75 +563,3 @@ interface WillMemberIdentity { ...@@ -562,75 +563,3 @@ interface WillMemberIdentity {
interface WillMemberIdentityWithPendingCerts extends WillMemberIdentity { interface WillMemberIdentityWithPendingCerts extends WillMemberIdentity {
pendingCertifications: PendingCert[] pendingCertifications: PendingCert[]
} }
class DataFinder {
private memBlocks: { [k: number]: any } = {}
private memCertsToTarget: { [k: number]: any } = {}
private memUidFromPub: { [k: number]: any } = {}
private memWotbIdFromPub: { [k: number]: any } = {}
constructor(protected duniterServer: Server) {
}
@MonitorExecutionTime()
findPendingMembers() {
return this.query('SELECT `buid`,`pubkey`,`uid`,`hash`,`expires_on`,`revocation_sig` FROM identities_pending WHERE `member`=0')
}
@MonitorExecutionTime()
findPendingCertsToTarget(toPubkey: string, hash: string) {
return DataFinder.getFromCacheOrDB(this.memCertsToTarget, [toPubkey, hash].join('-'), () => this.query(
'SELECT `from`,`block_number`,`block_hash`,`expires_on` FROM certifications_pending WHERE `to`=\''+toPubkey+'\' AND `target`=\''+hash+'\' ORDER BY `expires_on` DESC'))
}
@MonitorExecutionTime()
getWotexInfos(uid: string) {
return this.duniterServer.dal.idtyDAL.query('' +
'SELECT hash, uid, pub, wotb_id FROM i_index WHERE uid = ? ' +
'UNION ALL ' + 'SELECT hash, uid, pubkey as pub, (SELECT NULL) AS wotb_id FROM idty WHERE uid = ?', [uid, uid])
}
@MonitorExecutionTime()
async getBlockMedianTimeAndHash(block_number: number): Promise<{ hash: string, medianTime: number }|undefined> {
return (await DataFinder.getFromCacheOrDB(this.memBlocks, String(block_number),() => this.duniterServer.dal.getBlock(block_number))) || undefined
}
@MonitorExecutionTime()
getUidOfPub(pub: string): Promise<{ uid: string }[]> {
return DataFinder.getFromCacheOrDB(this.memUidFromPub, pub, () => this.query('SELECT `uid` FROM i_index WHERE `pub`=\''+pub+'\' LIMIT 1'))
}
@MonitorExecutionTime()
async getWotbIdByIssuerPubkey(issuerPubkey: string) {
return DataFinder.getFromCacheOrDB(this.memWotbIdFromPub, issuerPubkey, async () => (await this.duniterServer.dal.iindexDAL.query('SELECT wotb_id FROM i_index WHERE pub = ? AND wotb_id IS NOT NULL', [issuerPubkey]))[0].wotb_id)
}
@MonitorExecutionTime()
getChainableOnByIssuerPubkey(issuerPubkey: string) {
return this.query('SELECT `chainable_on` FROM c_index WHERE `issuer`=\''+issuerPubkey+'\' ORDER BY `chainable_on` DESC LIMIT 1')
}
@MonitorExecutionTime()
getCurrentBlockOrNull() {
return this.duniterServer.dal.getCurrentBlockOrNull()
}
query(sql: string, params?: any[]) {
return this.duniterServer.dal.peerDAL.query(sql, params || [])
}
static async getFromCacheOrDB<T>(cache: { [k: string]: any }, key: string, fetcher: () => Promise<T>) {
if (cache[key]) {
return cache[key]
}
return cache[key] = await fetcher()
}
invalidateCache() {
this.memBlocks = {}
this.memCertsToTarget = {}
this.memUidFromPub = {}
this.memWotbIdFromPub = {}
}
}
...@@ -12,7 +12,8 @@ ...@@ -12,7 +12,8 @@
"experimentalDecorators": true "experimentalDecorators": true
}, },
"include": [ "include": [
"routes" "routes",
"lib"
], ],
"compileOnSave": true "compileOnSave": true
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment