**Motivations:** - Réduction drastique de la consommation mémoire lors des ancrages - Élimination du chargement de 173k+ UTXOs à chaque requête - Stabilisation de la mémoire système sous charge élevée (50+ ancrages/minute) **Root causes:** - api-anchorage chargeait tous les UTXOs (173k+) via listunspent RPC à chaque ancrage - Filtrage et tri de 173k+ objets en mémoire pour sélectionner un seul UTXO - Croissance mémoire de ~16 MB toutes les 12 secondes avec 50 ancrages/minute - Saturation mémoire système en quelques minutes **Correctifs:** - Création du module database.js pour gérer la base de données SQLite partagée - Remplacement de listunspent RPC par requête SQL directe avec LIMIT 1 - Sélection directe d'un UTXO depuis la DB au lieu de charger/filtrer 173k+ objets - Marquage des UTXOs comme dépensés dans la DB après utilisation - Fermeture propre de la base de données lors de l'arrêt **Evolutions:** - Utilisation de la base de données SQLite partagée avec signet-dashboard - Réduction mémoire de 99.999% (173k+ objets → 1 objet par requête) - Amélioration des performances (requête SQL indexée vs filtrage en mémoire) - Optimisation mémoire de signet-dashboard (chargement UTXOs seulement si nécessaire) - Monitoring de lockedUtxos dans api-anchorage pour détecter les fuites - Nettoyage des intervalles frontend pour éviter les fuites mémoire **Pages affectées:** - api-anchorage/src/database.js (nouveau) - api-anchorage/src/bitcoin-rpc.js - api-anchorage/src/server.js - api-anchorage/package.json - signet-dashboard/src/bitcoin-rpc.js - signet-dashboard/public/app.js - features/optimisation-memoire-applications.md (nouveau) - features/api-anchorage-optimisation-base-donnees.md (nouveau)
100 lines
3.0 KiB
JavaScript
100 lines
3.0 KiB
JavaScript
/**
|
|
* Script d'initialisation de la base de données SQLite
|
|
* Crée les tables et les index nécessaires
|
|
*/
|
|
|
|
import { join, dirname } from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
import { createRequire } from 'module';
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = dirname(__filename);
|
|
|
|
// Utiliser better-sqlite3 depuis signet-dashboard/node_modules
|
|
const require = createRequire(join(__dirname, '../signet-dashboard/package.json'));
|
|
const Database = require('better-sqlite3');
|
|
|
|
const dbPath = join(__dirname, 'signet.db');
|
|
const db = new Database(dbPath);
|
|
|
|
// Activer les clés étrangères
|
|
db.pragma('foreign_keys = ON');
|
|
|
|
// Table utxos
|
|
db.exec(`
|
|
CREATE TABLE IF NOT EXISTS utxos (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
category TEXT NOT NULL,
|
|
txid TEXT NOT NULL,
|
|
vout INTEGER NOT NULL,
|
|
address TEXT,
|
|
amount REAL NOT NULL,
|
|
confirmations INTEGER DEFAULT 0,
|
|
is_anchor_change BOOLEAN DEFAULT FALSE,
|
|
block_time INTEGER,
|
|
is_spent_onchain BOOLEAN DEFAULT FALSE,
|
|
is_locked_in_mutex BOOLEAN DEFAULT FALSE,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
UNIQUE(txid, vout)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_utxos_category ON utxos(category);
|
|
CREATE INDEX IF NOT EXISTS idx_utxos_txid_vout ON utxos(txid, vout);
|
|
CREATE INDEX IF NOT EXISTS idx_utxos_confirmations ON utxos(confirmations);
|
|
CREATE INDEX IF NOT EXISTS idx_utxos_amount ON utxos(amount);
|
|
CREATE INDEX IF NOT EXISTS idx_utxos_is_spent ON utxos(is_spent_onchain);
|
|
`);
|
|
|
|
// Table anchors (hash_list.txt)
|
|
db.exec(`
|
|
CREATE TABLE IF NOT EXISTS anchors (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
hash TEXT NOT NULL UNIQUE,
|
|
txid TEXT NOT NULL,
|
|
block_height INTEGER,
|
|
confirmations INTEGER DEFAULT 0,
|
|
date TIMESTAMP,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_anchors_hash ON anchors(hash);
|
|
CREATE INDEX IF NOT EXISTS idx_anchors_txid ON anchors(txid);
|
|
CREATE INDEX IF NOT EXISTS idx_anchors_block_height ON anchors(block_height);
|
|
`);
|
|
|
|
// Table fees (fees_list.txt)
|
|
db.exec(`
|
|
CREATE TABLE IF NOT EXISTS fees (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
txid TEXT NOT NULL UNIQUE,
|
|
fee REAL NOT NULL,
|
|
fee_sats INTEGER NOT NULL,
|
|
block_height INTEGER,
|
|
block_time INTEGER,
|
|
confirmations INTEGER DEFAULT 0,
|
|
change_address TEXT,
|
|
change_amount REAL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_fees_txid ON fees(txid);
|
|
CREATE INDEX IF NOT EXISTS idx_fees_block_height ON fees(block_height);
|
|
`);
|
|
|
|
// Table cache pour suivre les mises à jour
|
|
db.exec(`
|
|
CREATE TABLE IF NOT EXISTS cache (
|
|
key TEXT PRIMARY KEY,
|
|
value TEXT NOT NULL,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
`);
|
|
|
|
console.log('✅ Base de données initialisée avec succès');
|
|
console.log(`📁 Fichier: ${dbPath}`);
|
|
|
|
db.close();
|