Skip to content

Commit bcf5d9a

Browse files
committed
close coin cache hive boxes when not in use
(cherry picked from commit b7b43e3)
1 parent cb10233 commit bcf5d9a

5 files changed

Lines changed: 65 additions & 63 deletions

File tree

lib/db/hive/db.dart

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class DB {
1616
// legacy (required for migrations)
1717
@Deprecated("Left over for migration from old versions of Stack Wallet")
1818
static const String boxNameAddressBook = "addressBook";
19+
static const String boxNameTrades = "exchangeTransactionsBox";
1920

2021
// in use
2122
// TODO: migrate
@@ -26,7 +27,6 @@ class DB {
2627
static const String boxNameWatchedTransactions =
2728
"watchedTxNotificationModels";
2829
static const String boxNameWatchedTrades = "watchedTradesNotificationModels";
29-
static const String boxNameTrades = "exchangeTransactionsBox";
3030
static const String boxNameTradesV2 = "exchangeTradesBox";
3131
static const String boxNameTradeNotes = "tradeNotesBox";
3232
static const String boxNameTradeLookup = "tradeToTxidLookUpBox";
@@ -38,10 +38,12 @@ class DB {
3838
static const String boxNameDBInfo = "dbInfo";
3939
static const String boxNamePrefs = "prefs";
4040

41-
String boxNameTxCache({required Coin coin}) => "${coin.name}_txCache";
42-
String boxNameSetCache({required Coin coin}) =>
41+
String _boxNameTxCache({required Coin coin}) => "${coin.name}_txCache";
42+
43+
// firo only
44+
String _boxNameSetCache({required Coin coin}) =>
4345
"${coin.name}_anonymitySetCache";
44-
String boxNameUsedSerialsCache({required Coin coin}) =>
46+
String _boxNameUsedSerialsCache({required Coin coin}) =>
4547
"${coin.name}_usedSerialsCache";
4648

4749
Box<NodeModel>? _boxNodeModels;
@@ -136,7 +138,6 @@ class DB {
136138
await Future.wait([
137139
Hive.openBox<dynamic>(boxNamePriceCache),
138140
_loadWalletBoxes(),
139-
_loadSharedCoinCacheBoxes(),
140141
]);
141142
}
142143

@@ -168,14 +169,39 @@ class DB {
168169
}
169170
}
170171

171-
Future<void> _loadSharedCoinCacheBoxes() async {
172-
for (final coin in Coin.values) {
173-
_txCacheBoxes[coin] =
174-
await Hive.openBox<dynamic>(boxNameTxCache(coin: coin));
175-
_setCacheBoxes[coin] =
176-
await Hive.openBox<dynamic>(boxNameSetCache(coin: coin));
177-
_usedSerialsCacheBoxes[coin] =
178-
await Hive.openBox<dynamic>(boxNameUsedSerialsCache(coin: coin));
172+
Future<Box<dynamic>> getTxCacheBox({required Coin coin}) async {
173+
return _txCacheBoxes[coin] ??=
174+
await Hive.openBox<dynamic>(_boxNameTxCache(coin: coin));
175+
}
176+
177+
Future<void> closeTxCacheBox({required Coin coin}) async {
178+
await _txCacheBoxes[coin]?.close();
179+
}
180+
181+
Future<Box<dynamic>> getAnonymitySetCacheBox({required Coin coin}) async {
182+
return _setCacheBoxes[coin] ??=
183+
await Hive.openBox<dynamic>(_boxNameSetCache(coin: coin));
184+
}
185+
186+
Future<void> closeAnonymitySetCacheBox({required Coin coin}) async {
187+
await _setCacheBoxes[coin]?.close();
188+
}
189+
190+
Future<Box<dynamic>> getUsedSerialsCacheBox({required Coin coin}) async {
191+
return _usedSerialsCacheBoxes[coin] ??=
192+
await Hive.openBox<dynamic>(_boxNameUsedSerialsCache(coin: coin));
193+
}
194+
195+
Future<void> closeUsedSerialsCacheBox({required Coin coin}) async {
196+
await _usedSerialsCacheBoxes[coin]?.close();
197+
}
198+
199+
/// Clear all cached transactions for the specified coin
200+
Future<void> clearSharedTransactionCache({required Coin coin}) async {
201+
await deleteAll<dynamic>(boxName: _boxNameTxCache(coin: coin));
202+
if (coin == Coin.firo) {
203+
await deleteAll<dynamic>(boxName: _boxNameSetCache(coin: coin));
204+
await deleteAll<dynamic>(boxName: _boxNameUsedSerialsCache(coin: coin));
179205
}
180206
}
181207

lib/electrumx_rpc/cached_electrumx.dart

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,8 @@ class CachedElectrumX {
2828
required Coin coin,
2929
}) async {
3030
try {
31-
final cachedSet = DB.instance.get<dynamic>(
32-
boxName: DB.instance.boxNameSetCache(coin: coin),
33-
key: groupId) as Map?;
31+
final box = await DB.instance.getAnonymitySetCacheBox(coin: coin);
32+
final cachedSet = box.get(groupId) as Map?;
3433

3534
Map<String, dynamic> set;
3635

@@ -61,7 +60,7 @@ class CachedElectrumX {
6160
: newSet["blockHash"];
6261
for (int i = (newSet["coins"] as List).length - 1; i >= 0; i--) {
6362
dynamic newCoin = newSet["coins"][i];
64-
List translatedCoin = [];
63+
List<dynamic> translatedCoin = [];
6564
translatedCoin.add(!isHexadecimal(newCoin[0] as String)
6665
? base64ToHex(newCoin[0] as String)
6766
: newCoin[0]);
@@ -81,10 +80,7 @@ class CachedElectrumX {
8180
set["coins"].insert(0, translatedCoin);
8281
}
8382
// save set to db
84-
await DB.instance.put<dynamic>(
85-
boxName: DB.instance.boxNameSetCache(coin: coin),
86-
key: groupId,
87-
value: set);
83+
await box.put(groupId, set);
8884
Logging.instance.log(
8985
"Updated current anonymity set for ${coin.name} with group ID $groupId",
9086
level: LogLevel.Info,
@@ -97,6 +93,8 @@ class CachedElectrumX {
9793
"Failed to process CachedElectrumX.getAnonymitySet(): $e\n$s",
9894
level: LogLevel.Error);
9995
rethrow;
96+
} finally {
97+
await DB.instance.closeAnonymitySetCacheBox(coin: coin);
10098
}
10199
}
102100

@@ -120,8 +118,9 @@ class CachedElectrumX {
120118
bool verbose = true,
121119
}) async {
122120
try {
123-
final cachedTx = DB.instance.get<dynamic>(
124-
boxName: DB.instance.boxNameTxCache(coin: coin), key: txHash) as Map?;
121+
final box = await DB.instance.getTxCacheBox(coin: coin);
122+
123+
final cachedTx = box.get(txHash) as Map?;
125124
if (cachedTx == null) {
126125
final Map<String, dynamic> result = await electrumXClient
127126
.getTransaction(txHash: txHash, verbose: verbose);
@@ -131,10 +130,7 @@ class CachedElectrumX {
131130

132131
if (result["confirmations"] != null &&
133132
result["confirmations"] as int > minCacheConfirms) {
134-
await DB.instance.put<dynamic>(
135-
boxName: DB.instance.boxNameTxCache(coin: coin),
136-
key: txHash,
137-
value: result);
133+
await box.put(txHash, result);
138134
}
139135

140136
Logging.instance.log("using fetched result", level: LogLevel.Info);
@@ -148,6 +144,8 @@ class CachedElectrumX {
148144
"Failed to process CachedElectrumX.getTransaction(): $e\n$s",
149145
level: LogLevel.Error);
150146
rethrow;
147+
} finally {
148+
await DB.instance.closeTxCacheBox(coin: coin);
151149
}
152150
}
153151

@@ -156,9 +154,9 @@ class CachedElectrumX {
156154
int startNumber = 0,
157155
}) async {
158156
try {
159-
final _list = DB.instance.get<dynamic>(
160-
boxName: DB.instance.boxNameUsedSerialsCache(coin: coin),
161-
key: "serials") as List?;
157+
final box = await DB.instance.getUsedSerialsCacheBox(coin: coin);
158+
159+
final _list = box.get("serials") as List?;
162160

163161
List<String> cachedSerials =
164162
_list == null ? [] : List<String>.from(_list);
@@ -178,10 +176,9 @@ class CachedElectrumX {
178176
}
179177
cachedSerials.addAll(newSerials);
180178

181-
await DB.instance.put<dynamic>(
182-
boxName: DB.instance.boxNameUsedSerialsCache(coin: coin),
183-
key: "serials",
184-
value: cachedSerials,
179+
await box.put(
180+
"serials",
181+
cachedSerials,
185182
);
186183

187184
return cachedSerials;
@@ -190,16 +187,13 @@ class CachedElectrumX {
190187
"Failed to process CachedElectrumX.getTransaction(): $e\n$s",
191188
level: LogLevel.Error);
192189
rethrow;
190+
} finally {
191+
await DB.instance.closeUsedSerialsCacheBox(coin: coin);
193192
}
194193
}
195194

196195
/// Clear all cached transactions for the specified coin
197196
Future<void> clearSharedTransactionCache({required Coin coin}) async {
198-
await DB.instance
199-
.deleteAll<dynamic>(boxName: DB.instance.boxNameTxCache(coin: coin));
200-
await DB.instance
201-
.deleteAll<dynamic>(boxName: DB.instance.boxNameSetCache(coin: coin));
202-
await DB.instance.deleteAll<dynamic>(
203-
boxName: DB.instance.boxNameUsedSerialsCache(coin: coin));
197+
await DB.instance.closeAnonymitySetCacheBox(coin: coin);
204198
}
205199
}

lib/utilities/db_version_migration.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import 'package:hive/hive.dart';
22
import 'package:isar/isar.dart';
3-
import 'package:stackduo/db/isar/main_db.dart';
43
import 'package:stackduo/db/hive/db.dart';
4+
import 'package:stackduo/db/isar/main_db.dart';
55
import 'package:stackduo/models/contact.dart';
66
import 'package:stackduo/models/exchange/change_now/exchange_transaction.dart';
77
import 'package:stackduo/models/exchange/response_objects/trade.dart';

test/cached_electrumx_test.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ void main() {
1313
group("tests using mock hive", () {
1414
setUp(() async {
1515
await setUpTestHive();
16+
// await Hive.openBox<dynamic>(
17+
// DB.instance.boxNameUsedSerialsCache(coin: Coin.firo));
18+
// await Hive.openBox<dynamic>(DB.instance.boxNameSetCache(coin: Coin.firo));
19+
// await Hive.openBox<dynamic>(DB.instance.boxNameTxCache(coin: Coin.firo));
1620
});
1721
group("getAnonymitySet", () {
1822
// test("empty set cache call", () async {

test/hive/db_test.dart

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
import 'package:flutter_test/flutter_test.dart';
22
import 'package:hive_test/hive_test.dart';
33
import 'package:stackduo/db/hive/db.dart';
4-
import 'package:stackduo/utilities/enums/coin_enum.dart';
54

65
void main() {
76
group("DB box names", () {
87
test("address book", () => expect(DB.boxNameAddressBook, "addressBook"));
9-
test("debug info", () => expect(DB.boxNameDebugInfo, "debugInfoBox"));
108
test("nodes", () => expect(DB.boxNameNodeModels, "nodeModels"));
119
test("primary nodes", () => expect(DB.boxNamePrimaryNodes, "primaryNodes"));
1210
test("wallets info", () => expect(DB.boxNameAllWalletsData, "wallets"));
@@ -33,26 +31,6 @@ void main() {
3331
expect(DB.boxNameWalletsToDeleteOnStart, "walletsToDeleteOnStart"));
3432
test("price cache",
3533
() => expect(DB.boxNamePriceCache, "priceAPIPrice24hCache"));
36-
37-
test("boxNameTxCache", () {
38-
for (final coin in Coin.values) {
39-
expect(DB.instance.boxNameTxCache(coin: coin), "${coin.name}_txCache");
40-
}
41-
});
42-
43-
test("boxNameSetCache", () {
44-
for (final coin in Coin.values) {
45-
expect(DB.instance.boxNameSetCache(coin: coin),
46-
"${coin.name}_anonymitySetCache");
47-
}
48-
});
49-
50-
test("boxNameUsedSerialsCache", () {
51-
for (final coin in Coin.values) {
52-
expect(DB.instance.boxNameUsedSerialsCache(coin: coin),
53-
"${coin.name}_usedSerialsCache");
54-
}
55-
});
5634
});
5735

5836
group("tests requiring test hive environment", () {

0 commit comments

Comments
 (0)