import 'dart:async'; // import 'dart:io'; import 'package:logging/logging.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; import 'mining_task_info.dart'; import '../utils/path_utils.dart'; /// 数据库管理服务 class DatabaseService { static final DatabaseService _instance = DatabaseService._internal(); factory DatabaseService() => _instance; DatabaseService._internal(); final Logger _logger = Logger('DatabaseService'); Database? _database; /// 初始化数据库 Future initialize() async { try { // Windows/Desktop: 使用 sqflite_common_ffi sqfliteFfiInit(); databaseFactory = databaseFactoryFfi; // 与 Go 版一致,尽量落到 ./bin/mining_task.db final dbPath = PathUtils.binFile('mining_task.db'); _database = await databaseFactory.openDatabase( dbPath, options: OpenDatabaseOptions( version: 1, onCreate: (db, version) async { await db.execute(''' CREATE TABLE mining_tasks ( id INTEGER PRIMARY KEY AUTOINCREMENT, coin TEXT NOT NULL, algo TEXT NOT NULL, pool TEXT NOT NULL, pool_url TEXT NOT NULL, wallet_address TEXT NOT NULL, worker_id TEXT NOT NULL, pool_user TEXT, wallet_mining INTEGER NOT NULL, end_timestamp INTEGER NOT NULL, miner TEXT NOT NULL, status TEXT NOT NULL, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL ) '''); }, ), ); _logger.info('数据库初始化成功'); } catch (e) { _logger.severe('数据库初始化失败: $e'); rethrow; } } /// 插入挖矿任务 Future insertMiningTask(MiningTaskInfo task) async { if (_database == null) { await initialize(); } try { final now = DateTime.now().millisecondsSinceEpoch ~/ 1000; return await _database!.insert( 'mining_tasks', { 'coin': task.coin, 'algo': task.algo, 'pool': task.pool, 'pool_url': task.poolUrl, 'wallet_address': task.walletAddress, 'worker_id': task.workerId, 'pool_user': task.poolUser, 'wallet_mining': task.walletMining ? 1 : 0, 'end_timestamp': task.endTimestamp, 'miner': task.miner, 'status': 'running', 'created_at': now, 'updated_at': now, }, ); } catch (e) { _logger.severe('插入挖矿任务失败: $e'); rethrow; } } /// 完成挖矿任务 Future finishMiningTask(int taskId) async { if (_database == null) { await initialize(); } try { final now = DateTime.now().millisecondsSinceEpoch ~/ 1000; await _database!.update( 'mining_tasks', { 'status': 'finished', 'updated_at': now, }, where: 'id = ?', whereArgs: [taskId], ); } catch (e) { _logger.severe('完成挖矿任务失败: $e'); } } /// 加载未完成的挖矿任务 Future loadUnfinishedTask() async { if (_database == null) { await initialize(); } try { final results = await _database!.query( 'mining_tasks', where: 'status = ?', whereArgs: ['running'], orderBy: 'created_at DESC', limit: 1, ); if (results.isEmpty) { return null; } final row = results.first; final currentTime = DateTime.now().millisecondsSinceEpoch ~/ 1000; final endTimestamp = row['end_timestamp'] as int; if (currentTime >= endTimestamp) { // 任务已过期,标记为完成 await finishMiningTask(row['id'] as int); return null; } return MiningTaskInfo( coin: row['coin'] as String, algo: row['algo'] as String, pool: row['pool'] as String, poolUrl: row['pool_url'] as String, walletAddress: row['wallet_address'] as String, workerId: row['worker_id'] as String, poolUser: row['pool_user'] as String?, walletMining: (row['wallet_mining'] as int) == 1, endTimestamp: endTimestamp, miner: row['miner'] as String, ); } catch (e) { _logger.severe('加载挖矿任务失败: $e'); return null; } } /// 获取任务历史 Future>> getTaskHistory({int limit = 100}) async { if (_database == null) { await initialize(); } try { return await _database!.query( 'mining_tasks', orderBy: 'created_at DESC', limit: limit, ); } catch (e) { _logger.severe('获取任务历史失败: $e'); return []; } } /// 关闭数据库 Future close() async { await _database?.close(); _database = null; } }