diff --git a/lib/services/plex_api_cache.dart b/lib/services/plex_api_cache.dart index c3d92b3e..2f19d128 100644 --- a/lib/services/plex_api_cache.dart +++ b/lib/services/plex_api_cache.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:isolate'; import 'package:drift/drift.dart'; @@ -40,7 +41,7 @@ class PlexApiCache { final result = await (_db.select(_db.apiCache)..where((t) => t.cacheKey.equals(key))).getSingleOrNull(); if (result != null) { - return jsonDecode(result.data) as Map; + return await Isolate.run(() => jsonDecode(result.data) as Map); } return null; } @@ -48,11 +49,10 @@ class PlexApiCache { /// Cache a response for an endpoint Future put(String serverId, String endpoint, Map data) async { final key = _buildKey(serverId, endpoint); + final encoded = await Isolate.run(() => jsonEncode(data)); await _db .into(_db.apiCache) - .insertOnConflictUpdate( - ApiCacheCompanion(cacheKey: Value(key), data: Value(jsonEncode(data)), cachedAt: Value(DateTime.now())), - ); + .insertOnConflictUpdate(ApiCacheCompanion(cacheKey: Value(key), data: Value(encoded), cachedAt: Value(DateTime.now()))); } /// Delete all cached data for a server @@ -130,27 +130,35 @@ class PlexApiCache { Future> getAllPinnedMetadata() async { final rows = await (_db.select(_db.apiCache)..where((t) => t.pinned.equals(true))).get(); - final result = {}; + // Extract (cacheKey, data) pairs and parse serverId/ratingKey on main thread (cheap string ops), + // then send raw JSON strings to isolate for the expensive decode+parse. + final entries = <(String serverId, String ratingKey, String data)>[]; for (final row in rows) { - // Extract serverId and ratingKey from cache key like "serverId:/library/metadata/12345" final colonIdx = row.cacheKey.indexOf(':'); if (colonIdx < 0) continue; final serverId = row.cacheKey.substring(0, colonIdx); final match = RegExp(r'/library/metadata/([^/]+)$').firstMatch(row.cacheKey); if (match == null) continue; - final ratingKey = match.group(1)!; - - try { - final data = jsonDecode(row.data) as Map; - final json = PlexCacheParser.extractFirstMetadata(data); - if (json == null) continue; - final metadata = PlexMetadata.fromJsonWithImages(json).copyWith(serverId: serverId); - result['$serverId:$ratingKey'] = metadata; - } catch (_) { - // Skip malformed entries - } + entries.add((serverId, match.group(1)!, row.data)); } - return result; + + if (entries.isEmpty) return {}; + + return await Isolate.run(() { + final result = {}; + for (final (serverId, ratingKey, rawData) in entries) { + try { + final data = jsonDecode(rawData) as Map; + final json = PlexCacheParser.extractFirstMetadata(data); + if (json == null) continue; + final metadata = PlexMetadata.fromJsonWithImages(json).copyWith(serverId: serverId); + result['$serverId:$ratingKey'] = metadata; + } catch (_) { + // Skip malformed entries + } + } + return result; + }); } /// Clear all cached data (useful for debugging/testing)