import 'dart:convert'; import 'dart:io'; import 'package:mutex/mutex.dart'; import 'package:twonly/globals.dart'; import 'package:twonly/src/utils/exclusive_access.utils.dart'; import 'package:twonly/src/utils/log.dart'; class KeyValueStore { static final Map _mutexes = {}; static Mutex _getMutex(String key) { return _mutexes.putIfAbsent(key, Mutex.new); } static Future _getFilePath(String key) async { return File('${AppEnvironment.supportDir}/keyvalue/$key.json'); } static Future _exclusive(String key, Future Function() action) { return exclusiveAccess( lockName: 'keyvalue-$key', mutex: _getMutex(key), action: action, ); } static Future delete(String key) => _exclusive(key, () async { try { final file = await _getFilePath(key); if (file.existsSync()) { file.deleteSync(); } } catch (e) { Log.error('Error deleting file: $e'); } }); static Future?> get(String key) async { return _exclusive(key, () async { final file = await _getFilePath(key); try { if (file.existsSync()) { final contents = await file.readAsString(); return jsonDecode(contents) as Map; } else { return null; } } catch (e) { Log.warn('Error reading file. Deleting it.: $e'); file.deleteSync(); return null; } }); } static Future put(String key, Map value) async { return _exclusive(key, () async { try { final file = await _getFilePath(key); await file.parent.create(recursive: true); await file.writeAsString(jsonEncode(value)); } catch (e) { Log.error('Error writing file: $e'); } }); } }