diff --git a/dental-server/database.js b/dental-server/database.js index be67ab9..9cd12bc 100644 --- a/dental-server/database.js +++ b/dental-server/database.js @@ -1,248 +1,109 @@ -const mysql = require('mysql2/promise'); -const fs = require('fs').promises; -const path = require('path'); +const { Pool } = require('pg'); let pool = null; -let sqliteDb = null; -const isSqlite = process.env.DB_TYPE === 'sqlite'; - -// Helper to rewrite MySQL-specific syntax to SQLite -function rewriteQuery(sql) { - if (!isSqlite) return sql; - - let query = sql; - // Replace NOW() with datetime('now') - query = query.replace(/\bNOW\(\)/gi, "datetime('now')"); - - // Rewrite ON DUPLICATE KEY UPDATE for users - if (query.includes('ON DUPLICATE KEY UPDATE')) { - query = `INSERT INTO users (username, email, password_hash, created_at) - VALUES (?, ?, ?, datetime('now')) - ON CONFLICT(username) DO UPDATE SET - email = excluded.email, - password_hash = excluded.password_hash`; - } - - return query; -} // ================================================================ -// INICIALIZAR BANCO DE DADOS +// FUNÇÕES AUXILIARES DE COMPATIBILIDADE (MYSQL -> POSTGRES) // ================================================================ -async function initSQLite() { - const { DatabaseSync } = require('node:sqlite'); - const dbPath = process.env.DB_PATH || path.join(__dirname, 'dental_images.db'); +function rewriteToPostgres(sql) { + let rewritten = sql; - sqliteDb = new DatabaseSync(dbPath); - console.log(`✅ Banco de dados SQLite criado/inicializado em: ${dbPath}`); + // 1. Converter MySQL NOW() para Postgres CURRENT_TIMESTAMP + rewritten = rewritten.replace(/\bNOW\(\)/gi, 'CURRENT_TIMESTAMP'); - // Criar tabelas para SQLite - sqliteDb.exec(` - CREATE TABLE IF NOT EXISTS users ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - username TEXT UNIQUE NOT NULL, - email TEXT UNIQUE NOT NULL, - password_hash TEXT NOT NULL, - clinic_name TEXT, - pc_name TEXT, - is_admin INTEGER DEFAULT 0, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP - ); - `); + // 2. Converter parâmetros de ? para $1, $2, etc. + let paramIndex = 1; + rewritten = rewritten.replace(/\?/g, () => `$${paramIndex++}`); - sqliteDb.exec(` - CREATE TABLE IF NOT EXISTS images ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - image_guid TEXT NOT NULL, - patient_name TEXT, - client_name TEXT, - original_filename TEXT, - filename TEXT NOT NULL, - enabled INTEGER DEFAULT 1, - tooth_number TEXT, - tooth_side TEXT, - patient_name_resumed TEXT, - original_image_id INTEGER, - rotation INTEGER DEFAULT 0, - flip_horizontal INTEGER DEFAULT 0, - flip_vertical INTEGER DEFAULT 0, - doctor TEXT, - remark TEXT, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP - ); - `); - - sqliteDb.exec(` - CREATE TABLE IF NOT EXISTS gtos ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - gto_number TEXT NOT NULL, - patient_name TEXT NOT NULL, - description TEXT, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP - ); - `); - - sqliteDb.exec(` - CREATE TABLE IF NOT EXISTS gto_images ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - gto_id INTEGER NOT NULL, - image_id INTEGER NOT NULL, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY(gto_id) REFERENCES gtos(id), - FOREIGN KEY(image_id) REFERENCES images(id) - ); - `); - - // Migrações para adicionar colunas se o banco já existia - try { - sqliteDb.exec("ALTER TABLE images ADD COLUMN doctor TEXT"); - } catch (e) { - // Coluna já existe - } - - try { - sqliteDb.exec("ALTER TABLE images ADD COLUMN remark TEXT"); - } catch (e) { - // Coluna já existe - } - - console.log('✅ Tabelas SQLite users e images criadas/verificadas'); - - // Migrações para adicionar colunas em users se o banco já existia - try { sqliteDb.exec("ALTER TABLE users ADD COLUMN clinic_name TEXT"); } catch (e) {} - try { sqliteDb.exec("ALTER TABLE users ADD COLUMN pc_name TEXT"); } catch (e) {} - try { sqliteDb.exec("ALTER TABLE users ADD COLUMN is_admin INTEGER DEFAULT 0"); } catch (e) {} - - // Criar administrador padrão se não houver usuários - try { - const stmtCount = sqliteDb.prepare('SELECT COUNT(*) as count FROM users'); - const userCount = stmtCount.get().count; - if (userCount === 0) { - console.log('⚠️ Nenhum usuário encontrado no SQLite. Criando admin padrão (admin / admin1234)...'); - const bcrypt = require('bcrypt'); - const passwordHash = bcrypt.hashSync('admin1234', 10); - const stmtInsert = sqliteDb.prepare(` - INSERT INTO users (username, email, password_hash, clinic_name, pc_name, is_admin) - VALUES (?, ?, ?, ?, ?, 1) - `); - stmtInsert.run('admin', 'admin@dental.local', passwordHash, 'Admin Clinic', 'Admin PC'); - console.log('✅ Usuário admin padrão criado com sucesso!'); + // 3. Adicionar RETURNING id nas inserções se não houver + if (rewritten.trim().toUpperCase().startsWith('INSERT INTO')) { + if (!rewritten.toUpperCase().includes('RETURNING')) { + rewritten += ' RETURNING id'; } - } catch (error) { - console.error('⚠️ Erro ao criar admin padrão:', error.message); } + + // 4. Reescrever ON DUPLICATE KEY UPDATE do MySQL + if (rewritten.includes('ON DUPLICATE KEY UPDATE')) { + // Isso é específico para a query de inserção de usuário default + rewritten = `INSERT INTO users (username, email, password_hash, created_at) + VALUES ($1, $2, $3, CURRENT_TIMESTAMP) + ON CONFLICT (username) DO UPDATE SET + email = EXCLUDED.email, + password_hash = EXCLUDED.password_hash + RETURNING id`; + } + + return rewritten; } +// ================================================================ +// INICIALIZAR BANCO DE DADOS POSTGRESQL +// ================================================================ + async function initDatabase() { - if (isSqlite) { - await initSQLite(); - return; + const dbConfig = { + host: process.env.DB_HOST || '10.99.0.3', + port: process.env.DB_PORT || 5432, + user: process.env.DB_USER || 'postgres', + database: process.env.DB_NAME || 'dental_images', + max: 20, // Max number of clients in the pool + idleTimeoutMillis: 30000, + }; + + if (process.env.DB_PASSWORD) { + dbConfig.password = process.env.DB_PASSWORD; } - + try { - const dbConfig = { - host: process.env.DB_HOST || 'localhost', - port: process.env.DB_PORT || 3306, - user: process.env.DB_USER || 'root', - password: process.env.DB_PASSWORD || '', - }; - const dbName = process.env.DB_NAME || 'dental_images'; + pool = new Pool(dbConfig); - // Criar pool temporário SEM database para poder criar o banco - const tempPool = mysql.createPool({ - ...dbConfig, - waitForConnections: true, - connectionLimit: 10, - queueLimit: 0 - }); + // Testa a conexão + const client = await pool.connect(); + console.log(`✅ Conectado ao PostgreSQL (Host: ${dbConfig.host}, DB: ${dbConfig.database})`); + client.release(); - console.log('✅ Pool de conexões MySQL criado'); - - // Verificar se banco existe, se não criar - try { - const [databases] = await tempPool.query( - `SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = ?`, - [dbName] - ); - - if (databases.length === 0) { - console.log(`⚠️ Banco ${dbName} não encontrado. Criando...`); - await tempPool.query(`CREATE DATABASE ${dbName} CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci`); - console.log(`✅ Banco ${dbName} criado!`); - } else { - console.log(`✅ Banco ${dbName} já existe`); - } - } catch (error) { - console.error('❌ Erro ao verificar/criar banco:', error); - throw error; - } - - // Fechar pool temporário - await tempPool.end(); - - // Criar pool definitivo COM database - pool = mysql.createPool({ - ...dbConfig, - database: dbName, - waitForConnections: true, - connectionLimit: 10, - queueLimit: 0, - enableKeepAlive: true, - keepAliveInitialDelay: 0 - }); - - // Testar conexão - const connection = await pool.getConnection(); - console.log('✅ Conectado ao MySQL'); - connection.release(); - - // Criar tabelas + // Criar as tabelas await createTables(); - } catch (error) { - console.error('❌ Erro ao conectar ao MySQL:', error.message); - console.error('Verifique:'); - console.error('1. MySQL está rodando? (sudo systemctl status mysql)'); - console.error('2. Credenciais corretas no .env?'); - console.error('3. Usuário tem permissão para criar databases?'); + console.error('❌ Erro ao conectar ao PostgreSQL:', error.message); throw error; } } // ================================================================ -// CRIAR TABELAS MYSQL +// CRIAR TABELAS POSTGRESQL // ================================================================ async function createTables() { - const connection = await pool.getConnection(); + const client = await pool.connect(); try { // Tabela de usuários - await connection.query(` + await client.query(` CREATE TABLE IF NOT EXISTS users ( - id INT AUTO_INCREMENT PRIMARY KEY, + id SERIAL PRIMARY KEY, username VARCHAR(50) UNIQUE NOT NULL, email VARCHAR(100) UNIQUE NOT NULL, password_hash TEXT NOT NULL, - clinic_name VARCHAR(100) NULL, - pc_name VARCHAR(50) NULL, - is_admin TINYINT(1) DEFAULT 0, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP - ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci + clinic_name VARCHAR(100), + pc_name VARCHAR(50), + is_admin BOOLEAN DEFAULT false, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ) `); - console.log('✅ Tabela users criada/verificada'); + console.log('✅ Tabela users criada/verificada no PostgreSQL'); // Tabela de imagens - await connection.query(` + await client.query(` CREATE TABLE IF NOT EXISTS images ( - id INT AUTO_INCREMENT PRIMARY KEY, + id SERIAL PRIMARY KEY, image_guid VARCHAR(255) NOT NULL, patient_name TEXT, client_name VARCHAR(100), original_filename TEXT, filename TEXT NOT NULL, - enabled TINYINT(1) DEFAULT 1, + enabled BOOLEAN DEFAULT true, tooth_number VARCHAR(10), tooth_side VARCHAR(10), patient_name_resumed VARCHAR(50), @@ -250,167 +111,99 @@ async function createTables() { rotation INT DEFAULT 0, flip_horizontal INT DEFAULT 0, flip_vertical INT DEFAULT 0, - doctor VARCHAR(255) NULL, - remark TEXT NULL, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - INDEX idx_images_enabled (enabled), - INDEX idx_images_original (original_image_id), - INDEX idx_patient_name (patient_name(100)), - INDEX idx_image_guid (image_guid), - INDEX idx_client_name (client_name), - INDEX idx_created_at (created_at) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci + doctor VARCHAR(255), + remark TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ) `); - console.log('✅ Tabela images criada/verificada'); + + // Criação de índices no PostgreSQL + await client.query('CREATE INDEX IF NOT EXISTS idx_images_enabled ON images(enabled)'); + await client.query('CREATE INDEX IF NOT EXISTS idx_images_original ON images(original_image_id)'); + await client.query('CREATE INDEX IF NOT EXISTS idx_image_guid ON images(image_guid)'); + await client.query('CREATE INDEX IF NOT EXISTS idx_client_name ON images(client_name)'); + await client.query('CREATE INDEX IF NOT EXISTS idx_created_at ON images(created_at)'); + + console.log('✅ Tabela images criada/verificada no PostgreSQL'); // Tabela GTOs - await connection.query(` + await client.query(` CREATE TABLE IF NOT EXISTS gtos ( - id INT AUTO_INCREMENT PRIMARY KEY, + id SERIAL PRIMARY KEY, gto_number VARCHAR(100) NOT NULL, patient_name VARCHAR(255) NOT NULL, description TEXT, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - INDEX idx_gtos_patient (patient_name) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ) `); - console.log('✅ Tabela gtos criada/verificada'); + await client.query('CREATE INDEX IF NOT EXISTS idx_gtos_patient ON gtos(patient_name)'); + console.log('✅ Tabela gtos criada/verificada no PostgreSQL'); // Tabela de vínculo GTO-Images - await connection.query(` + await client.query(` CREATE TABLE IF NOT EXISTS gto_images ( - id INT AUTO_INCREMENT PRIMARY KEY, - gto_id INT NOT NULL, - image_id INT NOT NULL, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (gto_id) REFERENCES gtos(id) ON DELETE CASCADE, - FOREIGN KEY (image_id) REFERENCES images(id) ON DELETE CASCADE, - UNIQUE INDEX idx_gto_image (gto_id, image_id) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci + id SERIAL PRIMARY KEY, + gto_id INT NOT NULL REFERENCES gtos(id) ON DELETE CASCADE, + image_id INT NOT NULL REFERENCES images(id) ON DELETE CASCADE, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + UNIQUE(gto_id, image_id) + ) `); - console.log('✅ Tabela gto_images criada/verificada'); + console.log('✅ Tabela gto_images criada/verificada no PostgreSQL'); - // Verificar e adicionar colunas se não existirem (migração) + // Verificar colunas faltantes em users (migração) try { - const columns = await connection.query(` - SELECT COLUMN_NAME - FROM INFORMATION_SCHEMA.COLUMNS - WHERE TABLE_SCHEMA = DATABASE() - AND TABLE_NAME = 'images' - AND COLUMN_NAME = 'client_name' + const res = await client.query(` + SELECT column_name + FROM information_schema.columns + WHERE table_name = 'users' AND column_name = 'clinic_name' `); - - if (columns[0].length === 0) { - console.log('⚠️ Coluna client_name não encontrada. Adicionando...'); - await connection.query(` - ALTER TABLE images - ADD COLUMN client_name VARCHAR(100) NULL - AFTER patient_name - `); - await connection.query(` - ALTER TABLE images - ADD INDEX idx_client_name (client_name) - `); - console.log('✅ Coluna client_name adicionada'); - } - } catch (error) { - console.warn('⚠️ Erro ao verificar/adicionar coluna client_name:', error.message); - } - - // Migração para coluna doctor - try { - const columnsDoctor = await connection.query(` - SELECT COLUMN_NAME - FROM INFORMATION_SCHEMA.COLUMNS - WHERE TABLE_SCHEMA = DATABASE() - AND TABLE_NAME = 'images' - AND COLUMN_NAME = 'doctor' - `); - if (columnsDoctor[0].length === 0) { - console.log('⚠️ Coluna doctor não encontrada. Adicionando...'); - await connection.query(` - ALTER TABLE images - ADD COLUMN doctor VARCHAR(255) NULL - AFTER client_name + if (res.rows.length === 0) { + console.log('⚠️ Adicionando novas colunas na tabela users...'); + await client.query(` + ALTER TABLE users + ADD COLUMN clinic_name VARCHAR(100), + ADD COLUMN pc_name VARCHAR(50), + ADD COLUMN is_admin BOOLEAN DEFAULT false `); } - } catch (error) { - console.warn('⚠️ Erro ao verificar/adicionar coluna doctor:', error.message); + } catch (e) { + console.warn('⚠️ Erro ao migrar tabela users:', e.message); } - // Migração para coluna remark + // Criar administrador padrão se não houver usuários try { - const columnsRemark = await connection.query(` - SELECT COLUMN_NAME - FROM INFORMATION_SCHEMA.COLUMNS - WHERE TABLE_SCHEMA = DATABASE() - AND TABLE_NAME = 'images' - AND COLUMN_NAME = 'remark' - `); - if (columnsRemark[0].length === 0) { - console.log('⚠️ Coluna remark não encontrada. Adicionando...'); - await connection.query(` - ALTER TABLE images - ADD COLUMN remark TEXT NULL - AFTER doctor - `); + const res = await client.query('SELECT COUNT(*) as count FROM users'); + if (parseInt(res.rows[0].count) === 0) { + console.log('⚠️ Nenhum usuário encontrado. Criando admin padrão (admin / admin1234)...'); + const bcrypt = require('bcrypt'); + const passwordHash = bcrypt.hashSync('admin1234', 10); + await client.query(` + INSERT INTO users (username, email, password_hash, clinic_name, pc_name, is_admin) + VALUES ($1, $2, $3, $4, $5, true) + `, ['admin', 'admin@dental.local', passwordHash, 'Admin Clinic', 'Admin PC']); + console.log('✅ Usuário admin padrão criado com sucesso!'); } } catch (error) { - console.warn('⚠️ Erro ao verificar/adicionar coluna remark:', error.message); - } - - // Migração para colunas da tabela users (clinic_name, pc_name, is_admin) - try { - const columnsUsers = await connection.query(` - SELECT COLUMN_NAME - FROM INFORMATION_SCHEMA.COLUMNS - WHERE TABLE_SCHEMA = DATABASE() - AND TABLE_NAME = 'users' - AND COLUMN_NAME = 'clinic_name' - `); - if (columnsUsers[0].length === 0) { - console.log('⚠️ Colunas de clínica em users não encontradas. Adicionando...'); - await connection.query(` - ALTER TABLE users - ADD COLUMN clinic_name VARCHAR(100) NULL AFTER password_hash, - ADD COLUMN pc_name VARCHAR(50) NULL AFTER clinic_name, - ADD COLUMN is_admin TINYINT(1) DEFAULT 0 AFTER pc_name - `); - // O primeiro usuário (admin padrão) deve virar admin se já existe - await connection.query(`UPDATE users SET is_admin = 1 ORDER BY id ASC LIMIT 1`); - } - } catch (error) { - console.warn('⚠️ Erro ao verificar/adicionar colunas de clínica em users:', error.message); + console.error('⚠️ Erro ao criar admin padrão:', error.message); } } catch (error) { - console.error('Erro ao criar tabelas:', error); + console.error('❌ Erro ao criar tabelas no PostgreSQL:', error); } finally { - connection.release(); + client.release(); } } // ================================================================ -// FUNÇÕES DE CONSULTA +// FUNÇÕES DE CONSULTA (ENVOLVENDO O POOL DO PG) // ================================================================ function get(query, params = []) { - if (isSqlite) { - return new Promise((resolve, reject) => { - try { - const stmt = sqliteDb.prepare(rewriteQuery(query)); - const row = stmt.get(...params); - resolve(row || null); - } catch (error) { - reject(error); - } - }); - } - return new Promise(async (resolve, reject) => { try { - const [rows] = await pool.query(query, params); - resolve(rows[0] || null); + const res = await pool.query(rewriteToPostgres(query), params); + resolve(res.rows[0] || null); } catch (error) { reject(error); } @@ -418,22 +211,10 @@ function get(query, params = []) { } function all(query, params = []) { - if (isSqlite) { - return new Promise((resolve, reject) => { - try { - const stmt = sqliteDb.prepare(rewriteQuery(query)); - const rows = stmt.all(...params); - resolve(rows); - } catch (error) { - reject(error); - } - }); - } - return new Promise(async (resolve, reject) => { try { - const [rows] = await pool.query(query, params); - resolve(rows); + const res = await pool.query(rewriteToPostgres(query), params); + resolve(res.rows || []); } catch (error) { reject(error); } @@ -441,27 +222,17 @@ function all(query, params = []) { } function run(query, params = []) { - if (isSqlite) { - return new Promise((resolve, reject) => { - try { - const stmt = sqliteDb.prepare(rewriteQuery(query)); - const result = stmt.run(...params); - resolve({ - lastID: result.lastInsertRowid, - changes: result.changes - }); - } catch (error) { - reject(error); - } - }); - } - return new Promise(async (resolve, reject) => { try { - const [result] = await pool.query(query, params); + const rewritten = rewriteToPostgres(query); + const res = await pool.query(rewritten, params); + + // No PostgreSQL, se adicionamos RETURNING id, o id estará no res.rows[0] + const insertedId = (res.rows && res.rows[0] && res.rows[0].id) ? res.rows[0].id : null; + resolve({ - lastID: result.insertId, - changes: result.affectedRows + lastID: insertedId, + changes: res.rowCount }); } catch (error) { reject(error); @@ -478,5 +249,5 @@ module.exports = { get, all, run, - get db() { return isSqlite ? sqliteDb : pool; } + get db() { return pool; } }; \ No newline at end of file diff --git a/dental-server/package.json b/dental-server/package.json index 149b0e0..4d2206f 100644 --- a/dental-server/package.json +++ b/dental-server/package.json @@ -16,16 +16,17 @@ "author": "Rcesar", "license": "MIT", "dependencies": { - "socket.io": "^4.7.2", - "express": "^4.18.2", - "sharp": "^0.32.6", - "mysql2": "^3.6.0", - "dotenv": "^16.3.1", - "cors": "^2.8.5", "bcrypt": "^5.1.1", - "jsonwebtoken": "^9.0.2", "cookie-parser": "^1.4.6", - "express-session": "^1.17.3" + "cors": "^2.8.5", + "dotenv": "^16.3.1", + "express": "^4.18.2", + "express-session": "^1.17.3", + "ioredis": "^5.10.1", + "jsonwebtoken": "^9.0.2", + "pg": "^8.21.0", + "sharp": "^0.32.6", + "socket.io": "^4.7.2" }, "engines": { "node": ">=16.0.0", diff --git a/dental-server/redis.js b/dental-server/redis.js new file mode 100644 index 0000000..6cee057 --- /dev/null +++ b/dental-server/redis.js @@ -0,0 +1,40 @@ +const Redis = require('ioredis'); + +let redisClient = null; + +function initRedis() { + const host = process.env.REDIS_HOST || '10.99.0.3'; + const port = process.env.REDIS_PORT || 6379; + const password = process.env.REDIS_PASSWORD || ''; + + redisClient = new Redis({ + host, + port, + password, + retryStrategy: (times) => { + // Reconecta exponencialmente com limite de 3 segundos + const delay = Math.min(times * 50, 3000); + return delay; + } + }); + + redisClient.on('connect', () => { + console.log(`✅ Conectado ao DragonflyDB/Redis em ${host}:${port}`); + }); + + redisClient.on('error', (err) => { + console.error('❌ Erro de conexão no DragonflyDB/Redis:', err.message); + }); +} + +function getClient() { + if (!redisClient) { + initRedis(); + } + return redisClient; +} + +module.exports = { + initRedis, + getClient +}; diff --git a/dental-server/server.js b/dental-server/server.js index 0a6decc..cafc885 100644 --- a/dental-server/server.js +++ b/dental-server/server.js @@ -18,6 +18,7 @@ const patientsRouter = require('./routes/patients'); const gtosRouter = require('./routes/gtos'); const systemRoutes = require('./routes/system'); const { checkInstallation } = require('./installer/check-installation'); +const redis = require('./redis'); // ================================================================ // CONFIGURAÇÃO DO SERVIDOR @@ -72,6 +73,18 @@ app.get('/status', (req, res) => { }); }); +// DragonflyDB Ping check +app.get('/api/redis/ping', async (req, res) => { + try { + const client = redis.getClient(); + await client.set('ping_test', 'pong', 'EX', 10); + const value = await client.get('ping_test'); + res.json({ success: true, dragonfly_db: 'connected', test_value: value }); + } catch (error) { + res.status(500).json({ success: false, error: error.message }); + } +}); + // Verificar se o nome do computador/cliente já existe app.get('/api/clients/check-name', async (req, res) => { try { @@ -911,6 +924,9 @@ async function start() { console.log('⚠️ Banco de dados não configurado. Execute a instalação em /install'); } + // Inicializar cliente DragonflyDB/Redis + redis.initRedis(); + // Iniciar servidor server.listen(PORT, () => { console.log('═══════════════════════════════════════════════════════'); diff --git a/docker-compose.yml b/docker-compose.yml index 871125e..cd73411 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,7 +12,7 @@ services: environment: - NODE_ENV=production - PORT=3000 - - DB_TYPE=sqlite + - DB_TYPE=postgres\n - DB_HOST=10.99.0.3\n - REDIS_HOST=10.99.0.3\n - REDIS_PORT=6379\n - REDIS_PASSWORD=clube67_db_pass_9903 - DB_PATH=/app/data/dental_images.db - DB_PORT=5432 - DB_USER=clube67