mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-01-03 17:29:23 +00:00
separate firo caches and add versioning
This commit is contained in:
parent
23db925e86
commit
2c07f2c13b
5 changed files with 142 additions and 43 deletions
|
@ -15,8 +15,8 @@ import '../../utilities/stack_file_system.dart';
|
||||||
|
|
||||||
part 'firo_cache_coordinator.dart';
|
part 'firo_cache_coordinator.dart';
|
||||||
part 'firo_cache_reader.dart';
|
part 'firo_cache_reader.dart';
|
||||||
part 'firo_cache_writer.dart';
|
|
||||||
part 'firo_cache_worker.dart';
|
part 'firo_cache_worker.dart';
|
||||||
|
part 'firo_cache_writer.dart';
|
||||||
|
|
||||||
/// Temporary debugging log function for this file
|
/// Temporary debugging log function for this file
|
||||||
void _debugLog(Object? object) {
|
void _debugLog(Object? object) {
|
||||||
|
@ -29,44 +29,73 @@ void _debugLog(Object? object) {
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class _FiroCache {
|
abstract class _FiroCache {
|
||||||
static const String sqliteDbFileName = "firo_ex_cache.sqlite3";
|
static const int _setCacheVersion = 1;
|
||||||
|
static const int _tagsCacheVersion = 1;
|
||||||
|
static const String sparkSetCacheFileName =
|
||||||
|
"spark_set_v$_setCacheVersion.sqlite3";
|
||||||
|
static const String sparkUsedTagsCacheFileName =
|
||||||
|
"spark_tags_v$_tagsCacheVersion.sqlite3";
|
||||||
|
|
||||||
static Database? _db;
|
static Database? _setCacheDB;
|
||||||
static Database get db {
|
static Database? _usedTagsCacheDB;
|
||||||
if (_db == null) {
|
static Database get setCacheDB {
|
||||||
|
if (_setCacheDB == null) {
|
||||||
throw Exception(
|
throw Exception(
|
||||||
"FiroCache.init() must be called before accessing FiroCache.db!",
|
"FiroCache.init() must be called before accessing FiroCache.db!",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return _db!;
|
return _setCacheDB!;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Database get usedTagsCacheDB {
|
||||||
|
if (_usedTagsCacheDB == null) {
|
||||||
|
throw Exception(
|
||||||
|
"FiroCache.init() must be called before accessing FiroCache.db!",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return _usedTagsCacheDB!;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void>? _initFuture;
|
static Future<void>? _initFuture;
|
||||||
static Future<void> init() => _initFuture ??= _init();
|
static Future<void> init() => _initFuture ??= _init();
|
||||||
|
|
||||||
static Future<void> _init() async {
|
static Future<void> _init() async {
|
||||||
final sqliteDir = await StackFileSystem.applicationSQLiteDirectory();
|
final sqliteDir =
|
||||||
|
await StackFileSystem.applicationFiroCacheSQLiteDirectory();
|
||||||
|
|
||||||
final file = File("${sqliteDir.path}/$sqliteDbFileName");
|
final sparkSetCacheFile = File("${sqliteDir.path}/$sparkSetCacheFileName");
|
||||||
|
final sparkUsedTagsCacheFile =
|
||||||
|
File("${sqliteDir.path}/$sparkUsedTagsCacheFileName");
|
||||||
|
|
||||||
final exists = await file.exists();
|
if (!(await sparkSetCacheFile.exists())) {
|
||||||
if (!exists) {
|
await _createSparkSetCacheDb(sparkSetCacheFile.path);
|
||||||
await _createDb(file.path);
|
}
|
||||||
|
if (!(await sparkUsedTagsCacheFile.exists())) {
|
||||||
|
await _createSparkUsedTagsCacheDb(sparkUsedTagsCacheFile.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
_db = sqlite3.open(
|
_setCacheDB = sqlite3.open(
|
||||||
file.path,
|
sparkSetCacheFile.path,
|
||||||
|
mode: OpenMode.readWrite,
|
||||||
|
);
|
||||||
|
_usedTagsCacheDB = sqlite3.open(
|
||||||
|
sparkUsedTagsCacheFile.path,
|
||||||
mode: OpenMode.readWrite,
|
mode: OpenMode.readWrite,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> _deleteAllCache() async {
|
static Future<void> _deleteAllCache() async {
|
||||||
final start = DateTime.now();
|
final start = DateTime.now();
|
||||||
db.execute(
|
setCacheDB.execute(
|
||||||
"""
|
"""
|
||||||
DELETE FROM SparkSet;
|
DELETE FROM SparkSet;
|
||||||
DELETE FROM SparkCoin;
|
DELETE FROM SparkCoin;
|
||||||
DELETE FROM SparkSetCoins;
|
DELETE FROM SparkSetCoins;
|
||||||
|
VACUUM;
|
||||||
|
""",
|
||||||
|
);
|
||||||
|
usedTagsCacheDB.execute(
|
||||||
|
"""
|
||||||
DELETE FROM SparkUsedCoinTags;
|
DELETE FROM SparkUsedCoinTags;
|
||||||
VACUUM;
|
VACUUM;
|
||||||
""",
|
""",
|
||||||
|
@ -77,7 +106,7 @@ abstract class _FiroCache {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> _createDb(String file) async {
|
static Future<void> _createSparkSetCacheDb(String file) async {
|
||||||
final db = sqlite3.open(
|
final db = sqlite3.open(
|
||||||
file,
|
file,
|
||||||
mode: OpenMode.readWriteCreate,
|
mode: OpenMode.readWriteCreate,
|
||||||
|
@ -109,7 +138,20 @@ abstract class _FiroCache {
|
||||||
FOREIGN KEY (setId) REFERENCES SparkSet(id),
|
FOREIGN KEY (setId) REFERENCES SparkSet(id),
|
||||||
FOREIGN KEY (coinId) REFERENCES SparkCoin(id)
|
FOREIGN KEY (coinId) REFERENCES SparkCoin(id)
|
||||||
);
|
);
|
||||||
|
""",
|
||||||
|
);
|
||||||
|
|
||||||
|
db.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> _createSparkUsedTagsCacheDb(String file) async {
|
||||||
|
final db = sqlite3.open(
|
||||||
|
file,
|
||||||
|
mode: OpenMode.readWriteCreate,
|
||||||
|
);
|
||||||
|
|
||||||
|
db.execute(
|
||||||
|
"""
|
||||||
CREATE TABLE SparkUsedCoinTags (
|
CREATE TABLE SparkUsedCoinTags (
|
||||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
||||||
tag TEXT NOT NULL UNIQUE
|
tag TEXT NOT NULL UNIQUE
|
||||||
|
|
|
@ -20,14 +20,18 @@ abstract class FiroCacheCoordinator {
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<String> getSparkCacheSize() async {
|
static Future<String> getSparkCacheSize() async {
|
||||||
final dir = await StackFileSystem.applicationSQLiteDirectory();
|
final dir = await StackFileSystem.applicationFiroCacheSQLiteDirectory();
|
||||||
final cacheFile = File("${dir.path}/${_FiroCache.sqliteDbFileName}");
|
final setCacheFile = File(
|
||||||
final int bytes;
|
"${dir.path}/${_FiroCache.sparkSetCacheFileName}",
|
||||||
if (await cacheFile.exists()) {
|
);
|
||||||
bytes = await cacheFile.length();
|
final usedTagsCacheFile = File(
|
||||||
} else {
|
"${dir.path}/${_FiroCache.sparkUsedTagsCacheFileName}",
|
||||||
bytes = 0;
|
);
|
||||||
}
|
final int bytes =
|
||||||
|
((await setCacheFile.exists()) ? await setCacheFile.length() : 0) +
|
||||||
|
((await usedTagsCacheFile.exists())
|
||||||
|
? await usedTagsCacheFile.length()
|
||||||
|
: 0);
|
||||||
|
|
||||||
if (bytes < 1024) {
|
if (bytes < 1024) {
|
||||||
return '$bytes B';
|
return '$bytes B';
|
||||||
|
@ -88,7 +92,7 @@ abstract class FiroCacheCoordinator {
|
||||||
static Future<Set<String>> getUsedCoinTags(int startNumber) async {
|
static Future<Set<String>> getUsedCoinTags(int startNumber) async {
|
||||||
final result = await _Reader._getSparkUsedCoinTags(
|
final result = await _Reader._getSparkUsedCoinTags(
|
||||||
startNumber,
|
startNumber,
|
||||||
db: _FiroCache.db,
|
db: _FiroCache.usedTagsCacheDB,
|
||||||
);
|
);
|
||||||
return result.map((e) => e["tag"] as String).toSet();
|
return result.map((e) => e["tag"] as String).toSet();
|
||||||
}
|
}
|
||||||
|
@ -99,7 +103,7 @@ abstract class FiroCacheCoordinator {
|
||||||
/// this table in practice.
|
/// this table in practice.
|
||||||
static Future<int> getUsedCoinTagsLastAddedRowId() async {
|
static Future<int> getUsedCoinTagsLastAddedRowId() async {
|
||||||
final result = await _Reader._getUsedCoinTagsLastAddedRowId(
|
final result = await _Reader._getUsedCoinTagsLastAddedRowId(
|
||||||
db: _FiroCache.db,
|
db: _FiroCache.usedTagsCacheDB,
|
||||||
);
|
);
|
||||||
if (result.isEmpty) {
|
if (result.isEmpty) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -112,7 +116,7 @@ abstract class FiroCacheCoordinator {
|
||||||
) async {
|
) async {
|
||||||
return await _Reader._checkTagIsUsed(
|
return await _Reader._checkTagIsUsed(
|
||||||
tag,
|
tag,
|
||||||
db: _FiroCache.db,
|
db: _FiroCache.usedTagsCacheDB,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +126,7 @@ abstract class FiroCacheCoordinator {
|
||||||
}) async {
|
}) async {
|
||||||
return await _Reader._getSetCoinsForGroupId(
|
return await _Reader._getSetCoinsForGroupId(
|
||||||
groupId,
|
groupId,
|
||||||
db: _FiroCache.db,
|
db: _FiroCache.setCacheDB,
|
||||||
newerThanTimeStamp: newerThanTimeStamp,
|
newerThanTimeStamp: newerThanTimeStamp,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -137,7 +141,7 @@ abstract class FiroCacheCoordinator {
|
||||||
) async {
|
) async {
|
||||||
final result = await _Reader._getLatestSetInfoForGroupId(
|
final result = await _Reader._getLatestSetInfoForGroupId(
|
||||||
groupId,
|
groupId,
|
||||||
db: _FiroCache.db,
|
db: _FiroCache.setCacheDB,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (result.isEmpty) {
|
if (result.isEmpty) {
|
||||||
|
@ -156,7 +160,7 @@ abstract class FiroCacheCoordinator {
|
||||||
) async {
|
) async {
|
||||||
return await _Reader._checkSetInfoForGroupIdExists(
|
return await _Reader._checkSetInfoForGroupIdExists(
|
||||||
groupId,
|
groupId,
|
||||||
db: _FiroCache.db,
|
db: _FiroCache.setCacheDB,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,10 @@ class _FiroCacheWorker {
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<_FiroCacheWorker> spawn() async {
|
static Future<_FiroCacheWorker> spawn() async {
|
||||||
final sqliteDir = await StackFileSystem.applicationSQLiteDirectory();
|
final dir = await StackFileSystem.applicationFiroCacheSQLiteDirectory();
|
||||||
final dbFilePath = "${sqliteDir.path}/${_FiroCache.sqliteDbFileName}";
|
final setCacheFilePath = "${dir.path}/${_FiroCache.sparkSetCacheFileName}";
|
||||||
|
final usedTagsCacheFilePath =
|
||||||
|
"${dir.path}/${_FiroCache.sparkUsedTagsCacheFileName}";
|
||||||
|
|
||||||
final initPort = RawReceivePort();
|
final initPort = RawReceivePort();
|
||||||
final connection = Completer<(ReceivePort, SendPort)>.sync();
|
final connection = Completer<(ReceivePort, SendPort)>.sync();
|
||||||
|
@ -45,7 +47,7 @@ class _FiroCacheWorker {
|
||||||
try {
|
try {
|
||||||
await Isolate.spawn(
|
await Isolate.spawn(
|
||||||
_startWorkerIsolate,
|
_startWorkerIsolate,
|
||||||
(initPort.sendPort, dbFilePath),
|
(initPort.sendPort, setCacheFilePath, usedTagsCacheFilePath),
|
||||||
);
|
);
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
initPort.close();
|
initPort.close();
|
||||||
|
@ -75,7 +77,8 @@ class _FiroCacheWorker {
|
||||||
static void _handleCommandsToIsolate(
|
static void _handleCommandsToIsolate(
|
||||||
ReceivePort receivePort,
|
ReceivePort receivePort,
|
||||||
SendPort sendPort,
|
SendPort sendPort,
|
||||||
Database db,
|
Database setCacheDb,
|
||||||
|
Database usedTagsCacheDb,
|
||||||
Mutex mutex,
|
Mutex mutex,
|
||||||
) {
|
) {
|
||||||
receivePort.listen((message) {
|
receivePort.listen((message) {
|
||||||
|
@ -87,11 +90,18 @@ class _FiroCacheWorker {
|
||||||
switch (task.func) {
|
switch (task.func) {
|
||||||
case FCFuncName._updateSparkAnonSetCoinsWith:
|
case FCFuncName._updateSparkAnonSetCoinsWith:
|
||||||
final data = task.data as (int, Map<String, dynamic>);
|
final data = task.data as (int, Map<String, dynamic>);
|
||||||
result = _updateSparkAnonSetCoinsWith(db, data.$2, data.$1);
|
result = _updateSparkAnonSetCoinsWith(
|
||||||
|
setCacheDb,
|
||||||
|
data.$2,
|
||||||
|
data.$1,
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FCFuncName._updateSparkUsedTagsWith:
|
case FCFuncName._updateSparkUsedTagsWith:
|
||||||
result = _updateSparkUsedTagsWith(db, task.data as List<String>);
|
result = _updateSparkUsedTagsWith(
|
||||||
|
usedTagsCacheDb,
|
||||||
|
task.data as List<String>,
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,14 +117,24 @@ class _FiroCacheWorker {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _startWorkerIsolate((SendPort, String) args) {
|
static void _startWorkerIsolate((SendPort, String, String) args) {
|
||||||
final receivePort = ReceivePort();
|
final receivePort = ReceivePort();
|
||||||
args.$1.send(receivePort.sendPort);
|
args.$1.send(receivePort.sendPort);
|
||||||
final mutex = Mutex();
|
final mutex = Mutex();
|
||||||
final db = sqlite3.open(
|
final setCacheDb = sqlite3.open(
|
||||||
args.$2,
|
args.$2,
|
||||||
mode: OpenMode.readWrite,
|
mode: OpenMode.readWrite,
|
||||||
);
|
);
|
||||||
_handleCommandsToIsolate(receivePort, args.$1, db, mutex);
|
final usedTagsCacheDb = sqlite3.open(
|
||||||
|
args.$3,
|
||||||
|
mode: OpenMode.readWrite,
|
||||||
|
);
|
||||||
|
_handleCommandsToIsolate(
|
||||||
|
receivePort,
|
||||||
|
args.$1,
|
||||||
|
setCacheDb,
|
||||||
|
usedTagsCacheDb,
|
||||||
|
mutex,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
|
|
||||||
|
import '../../../db/sqlite/firo_cache.dart';
|
||||||
import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart';
|
import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart';
|
||||||
import '../../../models/isar/models/isar_models.dart';
|
import '../../../models/isar/models/isar_models.dart';
|
||||||
import '../../../pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart';
|
import '../../../pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart';
|
||||||
|
@ -282,6 +283,24 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
if (wallet.isarTransactionVersion == 2 &&
|
||||||
|
wallet is FiroWallet)
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
"sparkCache: ",
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 2,
|
||||||
|
),
|
||||||
|
FutureBuilder(
|
||||||
|
future: FiroCacheCoordinator.getSparkCacheSize(),
|
||||||
|
builder: (_, snapshot) => Text(
|
||||||
|
snapshot.data ?? "",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
|
|
|
@ -91,10 +91,24 @@ abstract class StackFileSystem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<Directory> applicationSQLiteDirectory() async {
|
// Not used in general now. See applicationFiroCacheSQLiteDirectory()
|
||||||
|
// static Future<Directory> applicationSQLiteDirectory() async {
|
||||||
|
// final root = await applicationRootDirectory();
|
||||||
|
// if (Util.isDesktop) {
|
||||||
|
// final dir = Directory("${root.path}/sqlite");
|
||||||
|
// if (!dir.existsSync()) {
|
||||||
|
// await dir.create();
|
||||||
|
// }
|
||||||
|
// return dir;
|
||||||
|
// } else {
|
||||||
|
// return root;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
static Future<Directory> applicationTorDirectory() async {
|
||||||
final root = await applicationRootDirectory();
|
final root = await applicationRootDirectory();
|
||||||
if (Util.isDesktop) {
|
if (Util.isDesktop) {
|
||||||
final dir = Directory("${root.path}/sqlite");
|
final dir = Directory("${root.path}/tor");
|
||||||
if (!dir.existsSync()) {
|
if (!dir.existsSync()) {
|
||||||
await dir.create();
|
await dir.create();
|
||||||
}
|
}
|
||||||
|
@ -104,10 +118,10 @@ abstract class StackFileSystem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<Directory> applicationTorDirectory() async {
|
static Future<Directory> applicationFiroCacheSQLiteDirectory() async {
|
||||||
final root = await applicationRootDirectory();
|
final root = await applicationRootDirectory();
|
||||||
if (Util.isDesktop) {
|
if (Util.isDesktop) {
|
||||||
final dir = Directory("${root.path}/tor");
|
final dir = Directory("${root.path}/sqlite/firo_cache");
|
||||||
if (!dir.existsSync()) {
|
if (!dir.existsSync()) {
|
||||||
await dir.create();
|
await dir.create();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue