Add mutex to putCache

This commit is contained in:
2024-05-27 11:48:20 +00:00
committed by GitHub
parent 682d24267f
commit b1fdf4cf9f
4 changed files with 73 additions and 53 deletions

View File

@@ -4,6 +4,7 @@ import 'dart:typed_data';
import 'package:file/file.dart';
import 'package:file/local.dart';
import 'package:logging/logging.dart';
import 'package:mutex/mutex.dart';
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
@@ -33,6 +34,7 @@ class ImageCaches {
static const version = 1;
int _size = 0;
int get size => _size;
late Mutex _mutex;
ImageCaches();
Future<String?> _desktopFilePath() async {
final String? exe = await platformPath.getCurrentExe();
@@ -166,6 +168,7 @@ class ImageCaches {
await _createDir();
if (!(await _checkDatabase())) await _createTable();
await _updateSize();
_mutex = Mutex();
_inited = true;
}
@@ -201,39 +204,42 @@ class ImageCaches {
Future<void> putCache(String uri, Uint8List data,
Map<String, List<String>> headers, String? realUri) async {
if (!_inited) return;
final u = Uri.parse(uri);
final dir = await cacheDir;
String p = path.join(dir.path, u.host.isEmpty ? "nohost" : u.host,
u.path.substring(1) + (u.hasQuery ? "?${u.query}" : ""));
final d = _fs.directory(path.dirname(p));
if (isWindows) {
if (path.isAbsolute(p)) {
p = p.substring(0, 2) +
p.substring(2).replaceAll(RegExp("[:\\*\\?\"\\<\\>\\|]"), '_');
} else {
p = p.replaceAll(RegExp("[:\\*\\?\"\\<\\>\\|]"), '_');
await _mutex.protect(() async {
final u = Uri.parse(uri);
final dir = await cacheDir;
String p = path.join(dir.path, u.host.isEmpty ? "nohost" : u.host,
u.path.substring(1) + (u.hasQuery ? "?${u.query}" : ""));
final d = _fs.directory(path.dirname(p));
if (isWindows) {
if (path.isAbsolute(p)) {
p = p.substring(0, 2) +
p.substring(2).replaceAll(RegExp("[:\\*\\?\"\\<\\>\\|]"), '_');
} else {
p = p.replaceAll(RegExp("[:\\*\\?\"\\<\\>\\|]"), '_');
}
}
}
if (!(await d.exists())) {
await d.create(recursive: true);
}
final f = _fs.file(p);
await f.writeAsBytes(data.toList());
final lastUsed = DateTime.now().millisecondsSinceEpoch;
final header = jsonEncode(headers);
if (_exeDir != null) {
p = path.relative(p, from: _exeDir!);
}
final exes = await _db!.query("images", where: 'url = ?', whereArgs: [uri]);
await _db!.rawInsert(
"INSERT OR REPLACE INTO images VALUES (?, ?, ?, ?, ?, ?);",
[uri, p, lastUsed, header, realUri, data.length]);
if (exes.isEmpty) {
_size += data.length;
} else {
final originalSize = (exes[0]["size"] as int?) ?? 0;
_size += (data.length - originalSize);
}
if (!(await d.exists())) {
await d.create(recursive: true);
}
final f = _fs.file(p);
await f.writeAsBytes(data.toList());
final lastUsed = DateTime.now().millisecondsSinceEpoch;
final header = jsonEncode(headers);
if (_exeDir != null) {
p = path.relative(p, from: _exeDir!);
}
final exes =
await _db!.query("images", where: 'url = ?', whereArgs: [uri]);
await _db!.rawInsert(
"INSERT OR REPLACE INTO images VALUES (?, ?, ?, ?, ?, ?);",
[uri, p, lastUsed, header, realUri, data.length]);
if (exes.isEmpty) {
_size += data.length;
} else {
final originalSize = (exes[0]["size"] as int?) ?? 0;
_size += (data.length - originalSize);
}
});
}
Future<void> updateSize({bool clear = false}) async {

View File

@@ -2,6 +2,7 @@ import 'dart:js_interop';
import 'dart:js_interop_unsafe';
import 'dart:typed_data';
import 'package:logging/logging.dart';
import 'package:mutex/mutex.dart';
import 'package:web/web.dart';
import 'web/indexed_db.dart';
@@ -14,6 +15,7 @@ class ImageCaches {
int get size => _size;
late IndexedDb _db;
bool _inited = false;
late Mutex _mutex;
Future<void> _updateSize() async {
int total = 0;
await _db.openCursor("images", (cur) {
@@ -51,6 +53,7 @@ class ImageCaches {
}, 1);
await _db.init();
await _updateSize();
_mutex = Mutex();
_inited = true;
}
@@ -90,27 +93,29 @@ class ImageCaches {
Future<void> putCache(String uri, Uint8List data,
Map<String, List<String>> headers, String? realUri) async {
if (!_inited) return;
final he = JSObject();
for (final e in headers.entries) {
he.setProperty(e.key.toJS, e.value.map((e) => e.toJS).toList().toJS);
}
final opts = ResponseInit(status: 200, statusText: 'OK', headers: he);
final lastUsed = DateTime.now().millisecondsSinceEpoch;
final res = Response(data.toJS, opts);
await cache.put(uri.toJS, res).toDart;
final oObj = (await _db.get("images", uri.toJS)) as JSObject?;
final obj = JSObject();
obj.setProperty("url".toJS, uri.toJS);
obj.setProperty("size".toJS, data.length.toJS);
obj.setProperty("last_used".toJS, lastUsed.toJS);
await _db.put("images", obj);
if (oObj == null) {
_size += data.length;
} else {
final originalSize =
(oObj!.getProperty("size".toJS) as JSNumber).toDartInt;
_size += (data.length - originalSize);
}
await _mutex.protect(() async {
final he = JSObject();
for (final e in headers.entries) {
he.setProperty(e.key.toJS, e.value.map((e) => e.toJS).toList().toJS);
}
final opts = ResponseInit(status: 200, statusText: 'OK', headers: he);
final lastUsed = DateTime.now().millisecondsSinceEpoch;
final res = Response(data.toJS, opts);
await cache.put(uri.toJS, res).toDart;
final oObj = (await _db.get("images", uri.toJS)) as JSObject?;
final obj = JSObject();
obj.setProperty("url".toJS, uri.toJS);
obj.setProperty("size".toJS, data.length.toJS);
obj.setProperty("last_used".toJS, lastUsed.toJS);
await _db.put("images", obj);
if (oObj == null) {
_size += data.length;
} else {
final originalSize =
(oObj!.getProperty("size".toJS) as JSNumber).toDartInt;
_size += (data.length - originalSize);
}
});
}
Future<void> updateSize({bool clear = false}) async {

View File

@@ -558,6 +558,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.5"
mutex:
dependency: "direct main"
description:
name: mutex
sha256: "8827da25de792088eb33e572115a5eb0d61d61a3c01acbc8bcbe76ed78f1a1f2"
url: "https://pub.dev"
source: hosted
version: "3.1.0"
package_config:
dependency: transitive
description:

View File

@@ -29,6 +29,7 @@ dependencies:
json_annotation: ^4.9.0
keymap: ^0.0.92
logging: ^1.2.0
mutex: ^3.1.0
package_info_plus: ^8.0.0
palette_generator: ^0.3.3+3
path: ^1.8.3