Repository: ktorio/ktor
File: ktor-client/ktor-client-core/jvm/src/io/ktor/client/plugins/cache/storage/FileCacheStorage.kt (Kotlin)

Code before:
                file.delete()
            } catch (cause: Exception) {
                LOGGER.trace { "Exception during cache deletion in a file: ${cause.stackTraceToString()}" }
            }
        }
    }

    private suspend fun writeCacheUnsafe(urlHex: String, caches: List<CachedResponseData>) {
        val channel = ByteChannel()
        try {
            coroutineScope {
                File(directory, urlHex).outputStream().buffered().use { output ->
                    launch {
                        channel.writeInt(caches.size)
                        for (cache in caches) {
                            writeCache(channel, cache)
                        }
                        channel.close()
                    }
                    channel.copyTo(output)
                }
            }
        } catch (cause: CancellationException) {
            throw cause
        } catch (cause: Exception) {
            LOGGER.trace { "Exception during saving a cache to a file: ${cause.stackTraceToString()}" }
        } finally {
            channel.close()
        }
    }

    private suspend fun readCacheUnsafe(urlHex: String): Set<CachedResponseData> {
        val file = File(directory, urlHex)
        if (!file.exists()) return emptySet()

        try {
            file.inputStream().buffered().use {
                val channel = it.toByteReadChannel()
                val requestsCount = channel.readInt()
                val caches = mutableSetOf<CachedResponseData>()
                for (i in 0 until requestsCount) {
                    caches.add(readCache(channel))
                }
                channel.discard()
                return caches
            }
        } catch (cause: Exception) {
            LOGGER.trace { "Exception during cache lookup in a file: ${cause.stackTraceToString()}" }
            return emptySet()
        }
    }

Review comment (performance):
Probably we should use `ensureActive()` instead of rethrowing `CancellationException`.
```suggestion
        } catch (cause: Exception) {
            if (cause is CancellationException) currentCoroutineContext().ensureActive()
            LOGGER.trace { "Exception during saving a cache to a file: ${cause.stackTraceToString()}" }
```
See [this discussion](https://github.com/Kotlin/kotlinx.coroutines/issues/3658#issuecomment-1943562914)

Code after:
                file.delete()
            } catch (cause: Exception) {
                LOGGER.trace { "Exception during cache deletion in a file: ${cause.stackTraceToString()}" }
            }
        }
    }

    private suspend fun writeCacheUnsafe(urlHex: String, caches: List<CachedResponseData>) {
        val channel = ByteChannel()
        try {
            coroutineScope {
                File(directory, urlHex).outputStream().buffered().use { output ->
                    launch {
                        channel.writeInt(caches.size)
                        for (cache in caches) {
                            writeCache(channel, cache)
                        }
                        channel.close()
                    }
                    channel.copyTo(output)
                }
            }
        } catch (cause: Exception) {
            if (cause is CancellationException) currentCoroutineContext().ensureActive()
            LOGGER.trace { "Exception during saving a cache to a file: ${cause.stackTraceToString()}" }
        } finally {
            channel.close()
        }
    }

    private suspend fun readCacheUnsafe(urlHex: String): Set<CachedResponseData> {
        val file = File(directory, urlHex)
        if (!file.exists()) return emptySet()

        try {
            file.inputStream().buffered().use {
                val channel = it.toByteReadChannel()
                val requestsCount = channel.readInt()
                val caches = mutableSetOf<CachedResponseData>()
                for (i in 0 until requestsCount) {
                    caches.add(readCache(channel))
                }
                channel.discard()
                return caches
            }
        } catch (cause: Exception) {
            LOGGER.trace { "Exception during cache lookup in a file: ${cause.stackTraceToString()}" }
            return emptySet()
        }
    }