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

feat: page willMembers en instantané

parent 3156aaa6
No related branches found
No related tags found
No related merge requests found
Pipeline #18696 failed
......@@ -51,7 +51,7 @@ module.exports = {
name: 'currency-monit [start|indexing] [host] [port]',
desc: 'Start duniter with module currency-monit or Indexing blockchain history',
preventIfRunning: true,
logs: false,
logs: true,
onDatabaseExecute: (server, conf, program, params, startServices) => co(function*() {
// currency-monit parameters
......
......@@ -6,6 +6,7 @@ const fs = require('fs');
const webserver = require(__dirname + '/webserver2.js');
const timestampToDatetime = require(__dirname + '/timestampToDatetime.js');
const {willMembers} = require("../modules/will-members");
/****************************
* Main algorithm
......@@ -51,6 +52,14 @@ module.exports = (duniterServer, host, port, appParente, program) => co(function
let httpServer = webserver(host, port, appParente, duniterServer, monitDatasPath, offset, cache, program.resetData);
yield httpServer.openConnection();
// On déclenche immédiatement une 1ère mise à jour de willMembers
willMembers(duniterServer)
.then(() => console.log('Initialisation de willMembers terminée'))
.catch((e) => {
console.error(e)
console.error('Initialisation de willMembers terminée avec erreur : ' + e.message)
})
})
.catch((err) => console.error(err.stack || err));
import {MonitConstants} from "../lib/constants2";
import {DBIdentity} from "duniter/app/lib/dal/sqliteDAL/IdentityDAL";
import {DBMembership} from "duniter/app/lib/dal/sqliteDAL/MembershipDAL";
import {showExecutionTimes} from "../lib/MonitorExecutionTime";
import {DataFinder} from "../lib/DataFinder";
import {Server} from "duniter/server";
import {WotBuilder} from "duniter/neon/lib";
import {
DetailedDistance,
PendingCert,
WillMemberIdentity,
WillMemberIdentityWithPendingCerts
} from "./willMembers/interfaces";
import {PendingCert, WillMemberIdentity, WillMemberIdentityWithPendingCerts} from "./willMembers/interfaces";
import {triParDateDeDisponibilite} from "./willMembers/triParDateDeDisponibilite";
import {WotbIdCache} from "./willMembers/wotbIdCache";
import {getIdentityListOrdered} from "./willMembers/getIdentityListOrdered";
......@@ -18,42 +11,88 @@ import {computeMeansAndCounts} from "./willMembers/computeMeansAndCounts";
import {getMembersQualityExt} from "./willMembers/getMembersQualityExt";
import {getSorting} from "./willMembers/getSorting";
import {SentryChecker} from "./willMembers/issuerIsSentry";
import {ConfDTO} from "duniter/app/lib/dto/ConfDTO";
// Préserver les résultats en cache
let lockWillMembers = false
let willMembersLastUptime = 0
let identitiesList: WillMemberIdentity[] = []
let idtysPendingCertifsList: PendingCert[][] = []
let nbMaxCertifs = 0
let countMembersWithSigQtyValidCert = 0
let idtysListOrdered: WillMemberIdentityWithPendingCerts[] = []
let membersQualityExt: { [p: string]: string } = {}
let meanSentriesReachedByIdtyPerCert: number[] = []
let meanMembersReachedByIdtyPerCert: number[] = []
let cacheBeingUpdatedSince = 0
let currentBlockchainTimestamp = 0
let currentMembersCount = 0
let currentBlockNumber = -1
let limitTimestamp = 0
export async function willMembers(duniterServer: Server, days = 65, order = 'desc', sort_by = 'registrationPackage', showIdtyWithZeroCert = 'no', sortSig = 'Availability') {
const dataFinder = await DataFinder.getInstanceReindexedIfNecessary()
const wotbIdCache = new WotbIdCache(dataFinder)
// get blockchain timestamp
let resultQueryCurrentBlock: any = await dataFinder.getCurrentBlockOrNull();
const currentBlockchainTimestamp = resultQueryCurrentBlock.medianTime;
const currentMembersCount = resultQueryCurrentBlock.membersCount;
const currentBlockNumber = resultQueryCurrentBlock.number;
// Initaliser les constantes
const conf = duniterServer.conf;
const dSen = Math.ceil(Math.pow(currentMembersCount, 1 / conf.stepMax));
// Calculer le timestamp limite à prendre en compte
let limitTimestamp = currentBlockchainTimestamp + (days*86400);
// Alimenter wotb avec la toile de confiance
const wotbInstance = duniterServer.dal.wotb;
const conf: ConfDTO = duniterServer.conf;
const dSen: number = Math.ceil(Math.pow(currentMembersCount, 1 / conf.stepMax));
// Vérifier si le cache doit être Réinitialiser
let reinitCache = (Math.floor(Date.now() / 1000) > (willMembersLastUptime + MonitConstants.MIN_WILLMEMBERS_UPDATE_FREQ));
// Si le cache willMembers est dévérouillé, le vérouiller, sinon ne pas réinitialiser le cache
if (reinitCache && !lockWillMembers) {
lockWillMembers = true;
} else if(lockWillMembers) {
if (reinitCache && !cacheBeingUpdatedSince) {
cacheBeingUpdatedSince = new Date().getTime();
} else if (cacheBeingUpdatedSince) {
reinitCache = false;
}
if (reinitCache) {
// En asynchrone
rechargeCache(duniterServer, days, dSen, conf, sortSig, sort_by, order)
.then(() => {
console.log('Cache mis à jour')
cacheBeingUpdatedSince = 0;
})
.catch((e) => {
console.error('Exception lors de la mise à jour du cache : ' + e.message)
console.error(e)
})
}
return {
days,
order,
sort_by,
showIdtyWithZeroCert,
sortSig,
idtysListOrdered,
currentBlockNumber,
currentBlockchainTimestamp,
currentMembersCount,
limitTimestamp,
dSen,
conf,
nbMaxCertifs,
countMembersWithSigQtyValidCert,
meanSentriesReachedByIdtyPerCert,
meanMembersReachedByIdtyPerCert,
membersQualityExt,
cacheBeingUpdatedSince
}
}
async function rechargeCache(duniterServer: Server, days: number, dSen: number, conf: ConfDTO, sortSig: string, sort_by: string, order: string) {
const dataFinder = await DataFinder.getInstanceReindexedIfNecessary()
const wotbIdCache = new WotbIdCache(dataFinder)
// get blockchain timestamp
let resultQueryCurrentBlock: any = await dataFinder.getCurrentBlockOrNull();
currentBlockchainTimestamp = resultQueryCurrentBlock.medianTime;
currentMembersCount = resultQueryCurrentBlock.membersCount;
currentBlockNumber = resultQueryCurrentBlock.number;
// Calculer le timestamp limite à prendre en compte
limitTimestamp = currentBlockchainTimestamp + (days*86400);
// Alimenter wotb avec la toile de confiance
const wotbInstance = duniterServer.dal.wotb;
// Réinitialiser le cache
dataFinder.invalidateCache()
identitiesList = [];
......@@ -183,7 +222,6 @@ export async function willMembers(duniterServer: Server, days = 65, order = 'des
countMembersWithSigQtyValidCert++;
}
} // END IDENTITIES LOOP
} // END if (reinitCache)
// Si demandé, retrier les, certifications par date de disponibilité
if (sortSig == "Availability") {
......@@ -194,7 +232,7 @@ export async function willMembers(duniterServer: Server, days = 65, order = 'des
let tabSort = getSorting(identitiesList, sort_by, currentBlockchainTimestamp, conf)
// Trier les identités
let idtysListOrdered: WillMemberIdentityWithPendingCerts[] = await getIdentityListOrdered(
idtysListOrdered = await getIdentityListOrdered(
identitiesList,
idtysPendingCertifsList,
currentBlockchainTimestamp,
......@@ -209,37 +247,12 @@ export async function willMembers(duniterServer: Server, days = 65, order = 'des
console.log('Calcul des qualités...')
let membersQualityExt = getMembersQualityExt(wotbInstance, idtysListOrdered, conf, dSen)
membersQualityExt = getMembersQualityExt(wotbInstance, idtysListOrdered, conf, dSen)
console.log('Calcul des moyennes...')
const {
meanSentriesReachedByIdtyPerCert,
meanMembersReachedByIdtyPerCert,
} = computeMeansAndCounts(idtysListOrdered, nbMaxCertifs)
if (reinitCache) {
lockWillMembers = false;
}
const meansAndCounts = computeMeansAndCounts(idtysListOrdered, nbMaxCertifs)
meanSentriesReachedByIdtyPerCert = meansAndCounts.meanSentriesReachedByIdtyPerCert
meanMembersReachedByIdtyPerCert = meansAndCounts.meanMembersReachedByIdtyPerCert
showExecutionTimes()
return {
days,
order,
sort_by,
showIdtyWithZeroCert,
sortSig,
idtysListOrdered,
currentBlockNumber,
currentBlockchainTimestamp,
currentMembersCount,
limitTimestamp,
dSen,
conf,
nbMaxCertifs,
countMembersWithSigQtyValidCert,
meanSentriesReachedByIdtyPerCert,
meanMembersReachedByIdtyPerCert,
membersQualityExt,
}
}
......@@ -33,6 +33,7 @@ module.exports = async (req: any, res: any, next: any) => {
meanSentriesReachedByIdtyPerCert,
meanMembersReachedByIdtyPerCert,
membersQualityExt,
cacheBeingUpdatedSince,
} = await willMembers(locals.duniterServer, req.query.d,
req.query.d && req.query.order,
req.query.sort_by,
......@@ -73,6 +74,7 @@ module.exports = async (req: any, res: any, next: any) => {
meanSentriesReachedByIdtyPerCert,
meanMembersReachedByIdtyPerCert,
membersQualityExt,
cacheBeingUpdatedSince,
// Template helpers
timestampToDatetime,
// Calculer la proportion de temps restant avant l'expiration
......
......@@ -44,25 +44,34 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD}
<!-- Afficher le menu -->
${printMenu(MENU_LANG, help, "WILL_MEMBERS")}
${(currentBlockNumber < 0)
? `<p style="padding: 8px; color: orange; background-color: lightgoldenrodyellow">Initialisation de currency-monit en cours...</p>`
: ``}
${(currentBlockNumber >= 0 && cacheBeingUpdatedSince) ?
`<p style="padding: 8px; color: darkblue; background-color: lightblue">Un recalcul est en cours, refraîchissez la page dans quelques secondes pour avoir la dernière version.</p>`
: (currentBlockNumber < 0) ? '' : `
<!-- Afficher le formulaire -->
<input type="number" name="d" value="${days}"/>${LANG["DAYS"]} - ${LANG["SORT_BY"]}
<select name="sort_by">
<option name="sort_by" value ="creationIdty">${LANG["SORT_BY_CREATION_IDTY"]}
<option name="sort_by" value ="sigCount" ${sort_by == 'sigCount' ? 'selected' : ''}>${LANG["SORT_BY_SIG_COUNT"]}
<option name="sort_by" value ="registrationPackage" ${sort_by == 'registrationPackage' ? 'selected' : ''}>${LANG["SORT_BY_REGISTRATION_PACKAGE"]}
</select> ${LANG["ORDER"]} : <select name="order">
<option name="order" value ="asc">${LANG["ORDER_ASC"]}
<option name="order" value ="desc" ${order == 'desc' ? 'selected' : ''}>${LANG["ORDER_DESC"]}
</select> <input type="submit" value="${LANG["SUBMIT_TXT"]}"><br>
<input type="checkbox" name="showIdtyWithZeroCert" value="yes" ${showIdtyWithZeroCert == 'yes' ? 'checked' : ''}>${LANG["CHECKBOX_SHOW_IDTY_WITH_ZERO_CERT"]}<br>
<input type="checkbox" name="sortSig" value="Availability" ${sortSig == 'Availability' ? 'checked' : ''}>${LANG["CHECKBOX_SORT_SIG"]}<br>
${LANG["IDTY_FILTER"]} : <input type="text" name="filter" id="filter" value="" maxlength="20" onchange="filterRows(document.getElementById('table'),2,0,this.value);" onkeypress="this.onchange();" onpaste="this.onchange();" oninput="this.onchange();"/>
</form>
<br>
<hr>
<!--<form>-->
<!-- <input type="number" name="d" value="${days}"/>${LANG["DAYS"]} - ${LANG["SORT_BY"]}-->
<!-- <select name="sort_by">-->
<!-- <option name="sort_by" value ="creationIdty">${LANG["SORT_BY_CREATION_IDTY"]}-->
<!-- <option name="sort_by" value ="sigCount" ${sort_by == 'sigCount' ? 'selected' : ''}>${LANG["SORT_BY_SIG_COUNT"]}-->
<!-- <option name="sort_by" value ="registrationPackage" ${sort_by == 'registrationPackage' ? 'selected' : ''}>${LANG["SORT_BY_REGISTRATION_PACKAGE"]}-->
<!-- </select> ${LANG["ORDER"]} : <select name="order">-->
<!-- <option name="order" value ="asc">${LANG["ORDER_ASC"]}-->
<!-- <option name="order" value ="desc" ${order == 'desc' ? 'selected' : ''}>${LANG["ORDER_DESC"]}-->
<!-- </select> <input type="submit" value="${LANG["SUBMIT_TXT"]}"><br>-->
<!-- <input type="checkbox" name="showIdtyWithZeroCert" value="yes" ${showIdtyWithZeroCert == 'yes' ? 'checked' : ''}>${LANG["CHECKBOX_SHOW_IDTY_WITH_ZERO_CERT"]}<br>-->
<!-- <input type="checkbox" name="sortSig" value="Availability" ${sortSig == 'Availability' ? 'checked' : ''}>${LANG["CHECKBOX_SORT_SIG"]}<br>-->
<!-- ${LANG["IDTY_FILTER"]} : <input type="text" name="filter" id="filter" value="" maxlength="20" onchange="filterRows(document.getElementById('table'),2,0,this.value);" onkeypress="this.onchange();" onpaste="this.onchange();" oninput="this.onchange();"/>-->
<!--</form>-->
<!--<br>-->
<!--<hr>-->
`
}
<!-- Afficher la légende et l'aide -->
${(help != 'no') ? `
${(currentBlockNumber >= 0 && help != 'no') ? `
<div id="zone1" style="width: 100%; height: 20px; background: White; border: 1px solid DimGrey; transition: height 1s; -moz-transition: height 1s;-webkit-transition: height 1s;-o-transition: height 1s; overflow: hidden;">
<div id="bandeau1" style="height: 20px; width: 100%; font-size: medium; color: white; background-color: darkgrey;" onmouseover="deroule(1,400);" onmouseout="deroule(1,20);"><b>${LANG["LEGEND"]}</b>
</div>
......@@ -85,6 +94,7 @@ ${(help != 'no') ? `
</div>
`:''}
${(currentBlockNumber < 0) ? '' : `
<!-- Afficher l'état de tension de la toile de confiance -->
<div id="zone2" style="width: 100%; height: 20px; background: White; border: 1px solid DimGrey; transition: height 1s; -moz-transition: height 1s;-webkit-transition: height 1s;-o-transition: height 1s; overflow: hidden;">
<div id="bandeau2" style="height: 20px; width: 100%; font-size: medium; color: white; background-color: darkgrey;" onmouseover="deroule(2,150);" onmouseout="deroule(2,20);"><b>${LANG["WOT_TENSION_STATE"]}</b>
......@@ -231,3 +241,4 @@ ${(help != 'no') ? `
</table><br>
<hr>
`}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment