Skip to content

Commit

Permalink
Refactor Nitrite cache to use Kotlin DSL and improve I/O handling
Browse files Browse the repository at this point in the history
This commit refactors the Nitrite cache configuration to use Kotlin's domain-specific language (DSL) for cleaner syntax. Additionally, all I/O operations involving the cache have been wrapped with Kotlin Coroutines' withContext(Dispatchers.IO) function, ensuring these tasks are performed on a background thread that won't block the main thread of execution. The changes affect multiple components, including 'PackageSearchApiPackageCache' and 'GradleUtils', along with related test cases.
  • Loading branch information
lamba92 committed May 14, 2024
1 parent 44a6d21 commit 310f6dc
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 2,409 deletions.
2,320 changes: 0 additions & 2,320 deletions aaa.patch

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ import com.jetbrains.packagesearch.plugin.core.PackageSearch
import com.jetbrains.packagesearch.plugin.core.utils.PKGSInternalAPI
import com.jetbrains.packagesearch.plugin.core.utils.packageSearchProjectDataPath
import kotlin.io.path.absolutePathString
import kotlin.io.path.createParentDirectories
import kotlin.io.path.div
import org.dizitart.kno2.getRepository
import org.dizitart.kno2.loadModule
import org.dizitart.kno2.nitrite
import org.dizitart.kno2.serialization.KotlinXSerializationMapper
import org.dizitart.no2.common.module.NitriteModule.module
import org.dizitart.no2.mvstore.MVStoreModule

@Service(Level.PROJECT)
Expand All @@ -23,10 +24,14 @@ class PackageSearchProjectCachesService(private val project: Project) : Disposab

@PKGSInternalAPI
val cache = nitrite {
loadModule(module(KotlinXSerializationMapper()))
loadModule(KotlinXSerializationMapper)
loadModule(
MVStoreModule.withConfig()
.filePath(cacheFilePath.absolutePathString())
.filePath(
cacheFilePath
.createParentDirectories()
.absolutePathString()
)
.compress(true)
.build()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import com.jetbrains.packagesearch.plugin.core.data.IconProvider
import com.jetbrains.packagesearch.plugin.core.data.PackageSearchDeclaredPackage
import com.jetbrains.packagesearch.plugin.core.data.PackageSearchModuleVariant
import com.jetbrains.packagesearch.plugin.core.extensions.PackageSearchModuleBuilderContext
import com.jetbrains.packagesearch.plugin.core.nitrite.NitriteFilters
import com.jetbrains.packagesearch.plugin.core.utils.PackageSearchProjectCachesService
import com.jetbrains.packagesearch.plugin.core.utils.icon
import com.jetbrains.packagesearch.plugin.core.utils.parseAttributesFromRawStrings
Expand All @@ -27,11 +26,14 @@ import java.nio.file.Path
import korlibs.crypto.sha512
import kotlin.contracts.contract
import kotlin.io.path.absolutePathString
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.singleOrNull
import kotlinx.coroutines.withContext
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import org.dizitart.kno2.filters.eq
import org.dizitart.no2.collection.UpdateOptions
import org.jetbrains.packagesearch.api.v3.ApiMavenPackage
import org.jetbrains.packagesearch.api.v3.ApiPackage
import org.jetbrains.packagesearch.api.v3.search.buildPackageTypes
Expand Down Expand Up @@ -255,14 +257,12 @@ private suspend fun Module.getDependenciesBySourceSet(buildFilePath: Path): Map<

val buildFileHash = vf.contentsToByteArray().sha512().hex

val entry = project.service<GradleKMPCacheService>()
.kmpDependencyRepository
.find(
filter = NitriteFilters.Object.eq(
path = GradleDependencyModelCacheEntry::buildFile,
value = buildFilePath.absolutePathString()
)
).singleOrNull()
val entry = withContext(Dispatchers.IO) {
project.service<GradleKMPCacheService>()
.kmpDependencyRepository
.find(GradleDependencyModelCacheEntry::buildFile eq buildFilePath.absolutePathString())
.singleOrNull()
}

if (entry?.buildFileSha == buildFileHash) return entry.dependencies

Expand All @@ -275,16 +275,13 @@ private suspend fun Module.getDependenciesBySourceSet(buildFilePath: Path): Map<
project.service<GradleKMPCacheService>()
.kmpDependencyRepository
.update(
filter = NitriteFilters.Object.eq(
path = GradleDependencyModelCacheEntry::buildFile,
value = buildFilePath.absolutePathString()
),
update = GradleKMPDependencyModelCacheEntry(
/* filter = */ GradleDependencyModelCacheEntry::buildFile eq buildFilePath.absolutePathString(),
/* update = */ GradleKMPDependencyModelCacheEntry(
buildFile = buildFilePath.absolutePathString(),
buildFileSha = buildFileHash,
dependencies = filteredDependenciesBySourceSet
),
upsert = true
/* updateOptions = */ UpdateOptions.updateOptions(true)
)

return filteredDependenciesBySourceSet
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package com.jetbrains.packagesearch.plugin.gradle.utils

import com.android.tools.idea.gradle.dsl.api.ProjectBuildModel
import com.intellij.buildsystem.model.unified.UnifiedDependencyRepository
import com.intellij.externalSystem.DependencyModifierService
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.readAction
import com.intellij.openapi.components.Service
Expand Down Expand Up @@ -32,18 +31,20 @@ import java.nio.file.Paths
import korlibs.crypto.sha512
import kotlin.contracts.contract
import kotlin.io.path.absolutePathString
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.singleOrNull
import kotlinx.coroutines.withContext
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import org.dizitart.kno2.filters.eq
import org.dizitart.no2.collection.UpdateOptions
import org.jetbrains.packagesearch.api.v3.ApiMavenPackage
import org.jetbrains.packagesearch.api.v3.ApiMavenRepository
import org.jetbrains.packagesearch.api.v3.ApiPackage
import org.jetbrains.packagesearch.api.v3.ApiRepository
import org.jetbrains.packagesearch.packageversionutils.normalization.NormalizedVersion

val gradleHomePathString: String
Expand Down Expand Up @@ -86,7 +87,7 @@ fun getModuleChangesFlow(model: PackageSearchGradleModel): Flow<Unit> {

@Serializable
data class GradleDependencyModelCacheEntry(
@SerialName("_id") val id: Long? = null,
@SerialName("_id") val id: String? = null,
val buildFile: String,
val buildFileSha: String,
val dependencies: List<GradleDependencyModel>,
Expand All @@ -98,14 +99,12 @@ suspend fun retrieveGradleDependencyModel(nativeModule: Module, buildFile: Path)

val buildFileSha = vf.contentsToByteArray().sha512().hex

val cache = project.service<GradleCacheService>()
.dependencyRepository
.find(
filter = NitriteFilters.Object.eq(
path = GradleDependencyModelCacheEntry::buildFile,
value = buildFile.absolutePathString()
)
).singleOrNull()
val cache = withContext(Dispatchers.IO) {
project.service<GradleCacheService>()
.dependencyRepository
.find(GradleDependencyModelCacheEntry::buildFile eq buildFile.absolutePathString())
.singleOrNull()
}

if (cache?.buildFileSha == buildFileSha) return cache.dependencies

Expand All @@ -120,16 +119,13 @@ suspend fun retrieveGradleDependencyModel(nativeModule: Module, buildFile: Path)
project.service<GradleCacheService>()
.dependencyRepository
.update(
filter = NitriteFilters.Object.eq(
path = GradleDependencyModelCacheEntry::buildFile,
value = buildFile.absolutePathString()
),
update = GradleDependencyModelCacheEntry(
/* filter = */ GradleDependencyModelCacheEntry::buildFile eq buildFile.absolutePathString(),
/* update = */ GradleDependencyModelCacheEntry(
buildFile = buildFile.absolutePathString(),
buildFileSha = buildFileSha,
dependencies = dependencies
),
upsert = true
/* updateOptions = */ UpdateOptions.updateOptions(true)
)

return dependencies
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import com.intellij.openapi.components.Service.Level
import com.intellij.openapi.components.service
import com.jetbrains.packagesearch.plugin.PackageSearchBundle
import com.jetbrains.packagesearch.plugin.core.PackageSearch
import com.jetbrains.packagesearch.plugin.core.nitrite.buildDefaultNitrate
import com.jetbrains.packagesearch.plugin.core.utils.IntelliJApplication
import com.jetbrains.packagesearch.plugin.core.utils.PKGSInternalAPI
import com.jetbrains.packagesearch.plugin.utils.ApiPackageCacheEntry
Expand All @@ -30,15 +29,22 @@ import io.ktor.client.plugins.logging.Logging
import io.ktor.client.request.headers
import java.util.concurrent.CompletableFuture
import kotlin.io.path.absolutePathString
import kotlin.io.path.createParentDirectories
import kotlin.io.path.div
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.future.future
import kotlinx.coroutines.launch
import org.dizitart.no2.IndexOptions
import org.dizitart.no2.IndexType
import kotlinx.coroutines.withContext
import org.dizitart.kno2.getRepository
import org.dizitart.kno2.loadModule
import org.dizitart.kno2.nitrite
import org.dizitart.kno2.serialization.KotlinXSerializationMapper
import org.dizitart.no2.index.IndexOptions
import org.dizitart.no2.index.IndexType
import org.dizitart.no2.mvstore.MVStoreModule
import org.jetbrains.packagesearch.api.v3.http.PackageSearchApiClient
import org.jetbrains.packagesearch.api.v3.http.PackageSearchEndpoints

Expand All @@ -51,28 +57,31 @@ class PackageSearchApplicationCachesService(private val coroutineScope: Coroutin
}

@PKGSInternalAPI
val cache = buildDefaultNitrate(
path = appSystemDir
.resolve(cacheFilePath)
.apply { parent.toFile().mkdirs() }
.absolutePathString()
)
val cache = nitrite {
loadModule(KotlinXSerializationMapper)
loadModule(
MVStoreModule.withConfig()
.filePath(
cacheFilePath
.createParentDirectories()
.absolutePathString()
)
.build()
)
}

override fun dispose() {
cache.close()
}

private inline fun <reified T : Any> getRepository(key: String) =
cache.getRepository<T>(key)

private val packagesRepository
get() = getRepository<ApiPackageCacheEntry>("packages")
get() = cache.getRepository<ApiPackageCacheEntry>("packages")

private val searchesRepository
get() = getRepository<ApiSearchCacheEntry>("searches")
get() = cache.getRepository<ApiSearchCacheEntry>("searches")

private val repositoryCache
get() = getRepository<ApiRepositoryCacheEntry>("repositories")
get() = cache.getRepository<ApiRepositoryCacheEntry>("repositories")

private val apiClient = PackageSearchApiClient(
endpoints = PackageSearchEndpoints.DEV,
Expand Down Expand Up @@ -103,18 +112,18 @@ class PackageSearchApplicationCachesService(private val coroutineScope: Coroutin
isOnline = { isOnlineFlow.value }
)

private suspend fun createIndexes() {
private suspend fun createIndexes() = withContext(Dispatchers.IO) {
searchesRepository.createIndex(
indexOptions = IndexOptions.indexOptions(IndexType.Unique),
path = ApiSearchCacheEntry::searchHash
IndexOptions.indexOptions(IndexType.UNIQUE),
ApiSearchCacheEntry::searchHash.name
)
packagesRepository.createIndex(
indexOptions = IndexOptions.indexOptions(IndexType.Unique),
path = ApiPackageCacheEntry::packageId
IndexOptions.indexOptions(IndexType.UNIQUE),
ApiPackageCacheEntry::packageId.name
)
packagesRepository.createIndex(
indexOptions = IndexOptions.indexOptions(IndexType.Unique),
path = ApiPackageCacheEntry::packageIdHash
IndexOptions.indexOptions(IndexType.UNIQUE),
ApiPackageCacheEntry::packageIdHash.name
)
}

Expand All @@ -138,10 +147,11 @@ class PackageSearchApplicationCachesService(private val coroutineScope: Coroutin
AsyncRecoveryResult(recoveryScope, emptyList())
}

private suspend fun clearCaches() {
searchesRepository.removeAll()
packagesRepository.removeAll()
repositoryCache.removeAll()
private suspend fun clearCaches() = withContext(Dispatchers.IO) {
searchesRepository.clear()
packagesRepository.clear()
repositoryCache.clear()
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.jetbrains.packagesearch.plugin.utils

import com.intellij.openapi.project.Project
import com.jetbrains.packagesearch.plugin.core.extensions.PackageSearchModuleBuilderContext
import com.jetbrains.packagesearch.plugin.core.nitrite.coroutines.CoroutineNitrite
import java.util.UUID
import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds
Expand All @@ -14,19 +13,15 @@ import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.channelFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
Expand Down
1 change: 1 addition & 0 deletions plugin/utils/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ dependencies {
api(packageSearchCatalog.packagesearch.api.client)
api(packageSearchCatalog.potassium.nitrite)
api(packageSearchCatalog.nitrite)
api(packageSearchCatalog.nitrite.mvstore.adapter)

testImplementation(kotlin("test-junit5"))
testImplementation(packageSearchCatalog.ktor.client.mock)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ data class ApiPackageCacheEntry(
val data: ApiPackage? = null,
val packageId: String? = null,
val packageIdHash: String? = null,
@SerialName("_id") val id: Long? = null,
@SerialName("_id") val id: String? = null,
val lastUpdated: Instant = Clock.System.now(),
) {
override fun toString() = buildString {
Expand All @@ -33,7 +33,7 @@ data class ApiSearchCacheEntry(
val packages: List<ApiPackage>,
val searchHash: String,
val original: SearchPackagesRequest,
@SerialName("_id") val id: Long? = null,
@SerialName("_id") val id: String? = null,
val lastUpdate: Instant = Clock.System.now(),
) {
override fun toString() = buildString {
Expand All @@ -47,7 +47,7 @@ data class ApiSearchCacheEntry(
@Serializable
data class ApiRepositoryCacheEntry(
val data: List<ApiRepository>,
@SerialName("_id") val id: Long? = null,
@SerialName("_id") val id: String? = null,
val lastUpdate: Instant = Clock.System.now(),
) {
override fun toString() = buildString {
Expand Down
Loading

0 comments on commit 310f6dc

Please sign in to comment.