@@ -21,141 +21,6 @@ class WebCacheManager(
2121 val openRs2Timestamp : Long?
2222 )
2323
24- companion object {
25- private const val TESTING_MODE = false
26- private val VERIFIED_INDICES = setOf (
27- OsrsCacheIndex .GAMEVALS .id,
28- OsrsCacheIndex .MODELS .id,
29- OsrsCacheIndex .SPRITES .id,
30- OsrsCacheIndex .TEXTURES .id,
31- OsrsCacheIndex .CONFIGS .id
32- )
33- private const val CACHE_INFO_FILE = " cache-info.json"
34- private const val MASTER_CHECKSUMS_FILE = " cache-master-checksums.json"
35- private const val DATA_CHECKSUM_FILE = " data.checksum"
36- private const val DATA_DIR = " data"
37- private const val CACHE_DIR = " cache"
38- }
39-
40- suspend fun loadOrUpdate (onUpdatingDetected : ((Boolean , Double? , String? ) -> Unit )? = null) = withContext(Dispatchers .IO ) {
41- checkAndUpdateCacheInfo(onUpdatingDetected)
42- lookingForChanges(onUpdatingDetected)
43- }
44-
45- suspend fun lookingForChanges (onUpdatingDetected : ((Boolean , Double? , String? ) -> Unit )? = null) = withContext(Dispatchers .IO ) {
46- val cacheDir = getCachePath()
47- val dataDir = File (cacheDir, DATA_DIR )
48-
49- if (! dataDir.exists() || ! dataDir.isDirectory) {
50- logger.warn(" Data directory does not exist, cannot scan for changes" )
51- return @withContext
52- }
53-
54- logger.info(" Scanning cache files for changes..." )
55- onUpdatingDetected?.invoke(true , null , " Verifying Cache checksum" )
56-
57- val cache = Cache .load(File (dataDir, CACHE_DIR ).toPath())
58- try {
59- val manifest = manifestManager.createManifest(cache)
60-
61- val masterChecksumFile = File (cacheDir, MASTER_CHECKSUMS_FILE )
62- val cacheNeedsDownload = ! File (cacheDir, CACHE_INFO_FILE ).exists()
63- val baseProgress = if (cacheNeedsDownload) 50.0 else 0.0
64- val progressRange = if (cacheNeedsDownload) 50.0 else 100.0
65-
66- val existingManifest = manifestManager.loadManifest(masterChecksumFile)
67-
68- if (existingManifest == null ) {
69- // First time - extract all files
70- val totalFiles = manifest.indices.values.flatMap { it.archives.values.flatMap { archive -> archive.files.values } }
71-
72- if (! TESTING_MODE ) {
73- manifestManager.saveManifest(manifest, masterChecksumFile)
74- logger.info(" Master checksum calculated and saved for ${totalFiles.size} files" )
75- } else {
76- logger.info(" Master checksum calculated for ${totalFiles.size} files (saving disabled for testing)" )
77- }
78-
79- updateFiles(cache, totalFiles, baseProgress, progressRange, onUpdatingDetected)
80- } else {
81- // Compare with existing manifest
82- val differences = manifestManager.findDifferences(existingManifest, manifest)
83- if (differences.added.isNotEmpty() || differences.removed.isNotEmpty()) {
84- logger.info(" Found ${differences.added.size} added/changed files and ${differences.removed.size} removed files" )
85-
86- // Delete all zip files since cache has changed
87- deleteZipFiles()
88-
89- if (! TESTING_MODE ) {
90- manifestManager.saveManifest(manifest, masterChecksumFile)
91- logger.debug(" Updated checksum manifest saved" )
92- }
93-
94- updateFiles(cache, differences.added, baseProgress, progressRange, onUpdatingDetected)
95- } else {
96- logger.info(" No changes detected in cache files" )
97-
98- // Update manifest timestamp even if no changes (to track when last checked)
99- if (! TESTING_MODE ) {
100- manifestManager.saveManifest(manifest, masterChecksumFile)
101- logger.debug(" Checksum manifest timestamp updated" )
102- }
103- }
104- }
105- } finally {
106- // Always cleanup cache, even if extraction failed
107- cleanupAfterExtraction(cache)
108- }
109-
110- onUpdatingDetected?.invoke(false , null , null )
111- }
112-
113- /* *
114- * Delete all zip files when cache is updated
115- */
116- private fun deleteZipFiles () {
117- zipService?.deleteAllZips()
118- }
119-
120- /* *
121- * Clean up resources after extraction is complete
122- * - Closes cache file handles
123- * - Clears temporary data structures
124- * - Forces garbage collection
125- * - Ensures threads are cleaned up
126- */
127- private suspend fun cleanupAfterExtraction (cache : Cache ) = withContext(Dispatchers .IO ) {
128- try {
129- logger.info(" Cleaning up extraction resources..." )
130-
131- // Close cache file handles if cache implements Closeable/AutoCloseable
132- try {
133- if (cache is AutoCloseable ) {
134- cache.close()
135- logger.debug(" Cache file handles closed" )
136- } else if (cache is java.io.Closeable ) {
137- cache.close()
138- logger.debug(" Cache file handles closed" )
139- }
140- } catch (e: Exception ) {
141- logger.warn(" Error closing cache: ${e.message} " )
142- }
143-
144- // Wait for any pending coroutines to complete
145- delay(50 )
146-
147- // Force garbage collection to free up memory
148- System .gc()
149-
150- // Give GC and threads a moment to finish
151- delay(50 )
152-
153- logger.info(" Cleanup completed" )
154- } catch (e: Exception ) {
155- logger.warn(" Error during cleanup: ${e.message} " , e)
156- }
157- }
158-
15924 private data class TargetResolution (
16025 val revision : Int ,
16126 val expectedStamp : DiffOpenRs2Stamp ?
@@ -286,8 +151,8 @@ class WebCacheManager(
286151 val env = config.environment.toString().lowercase()
287152 val cacheInfo = OpenRS2 .allCaches.firstOrNull {
288153 it.id == cacheId &&
289- it.game.contains(game) &&
290- it.environment.equals(env, true )
154+ it.game.contains(game) &&
155+ it.environment.equals(env, true )
291156 } ? : return null
292157 return toStamp(cacheInfo)
293158 }
@@ -307,4 +172,3 @@ class WebCacheManager(
307172 }
308173
309174}
310-
0 commit comments