Skip to content

Commit

Permalink
chore: data access layer
Browse files Browse the repository at this point in the history
  • Loading branch information
kmruiz committed May 23, 2024
1 parent 620ebe8 commit c296636
Show file tree
Hide file tree
Showing 20 changed files with 557 additions and 236 deletions.
6 changes: 5 additions & 1 deletion gradle/diktat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@
- name: TOO_MANY_PARAMETERS
enabled: true
configuration:
maxParameterListSize: '10'
maxParameterListSize: '10'
- name: FILE_NAME_INCORRECT
enabled: false
- name: LOCAL_VARIABLE_EARLY_DECLARATION
enabled: false
19 changes: 16 additions & 3 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ jmh-plugin="0.7.2"
diktat-plugin="1.0.1"
jmhreport-plugin="0.9.0"
# Library dependencies
kotlin-stdlib="1.9.22"
kotlinx-coroutines="1.7.3"
kotlin-stdlib="1.9.24"
kotlinx-coroutines="1.8.0"
jupiter="5.10.2"
mockito="5.11.0"
mockito-kotlin="5.3.1"
Expand All @@ -27,6 +27,8 @@ video-recorder="2.0"
gson="2.10.1"
mongodb-driver="5.1.0"
owasp-encoder="1.2.3"
testContainers="1.19.8"
intellij-database="241.15989.150"

[plugins]
intellij={ id="org.jetbrains.intellij", version.ref="intellij-plugin" }
Expand All @@ -45,6 +47,14 @@ kotlin-coroutines-core={ group="org.jetbrains.kotlinx", name="kotlinx-coroutines
kotlin-coroutines-swing={ group="org.jetbrains.kotlinx", name="kotlinx-coroutines-swing", version.ref="kotlinx-coroutines" }
kotlin-coroutines-test={ group="org.jetbrains.kotlinx", name="kotlinx-coroutines-test", version.ref="kotlinx-coroutines" }
######################################################
## IntelliJ compileOnly libraries. They must not be bundled because they are already part of the
## JetBrains ecosystem.
intellij-database-sql={ group="com.jetbrains.intellij.database", name="database-sql", version.ref="intellij-database" }
intellij-database-connectivity={ group="com.jetbrains.intellij.database", name="database-connectivity", version.ref="intellij-database" }
intellij-database-jdbc-console={ group="com.jetbrains.intellij.database", name="database-jdbc-console", version.ref="intellij-database" }
intellij-database-core-base={ group="com.jetbrains.intellij.database", name="database", version.ref="intellij-database" }
intellij-database-core-impl={ group="com.jetbrains.intellij.database", name="database-core-impl", version.ref="intellij-database" }
######################################################
## Production Libraries.
segment={ group="com.segment.analytics.java", name="analytics", version.ref="segment" }
gson={ group="com.google.code.gson", name="gson", version.ref="gson" }
Expand All @@ -62,13 +72,16 @@ testing-remoteRobot={ group="com.intellij.remoterobot", name="remote-robot", ver
testing-remoteRobotDeps-remoteFixtures={ group="com.intellij.remoterobot", name="remote-fixtures", version.ref="intellij-remoteRobot"}
testing-remoteRobotDeps-ideLauncher={ group="com.intellij.remoterobot", name="ide-launcher", version.ref="intellij-remoteRobot"}
testing-remoteRobotDeps-okHttp={ group="com.squareup.okhttp3", name="okhttp", version.ref="okHttp" }
testing-intellij-ideImpl={ group="com.jetbrains.intellij.platform", name="ide-impl", version.ref="intellij-testBuild" }
testing-intellij-ideImpl={ group="com.jetbrains.intellij.platform", name="ide", version.ref="intellij-testBuild" }
testing-intellij-coreUi={ group="com.jetbrains.intellij.platform", name="core-ui", version.ref="intellij-testBuild" }
testing-remoteRobotDeps-retrofit={ group="com.squareup.retrofit2", name="retrofit", version.ref="retrofit" }
testing-remoteRobotDeps-retrofitGson={ group="com.squareup.retrofit2", name="converter-gson", version.ref="retrofit" }
testing-jmh-core={ group="org.openjdk.jmh", name="jmh-core", version.ref="jmh" }
testing-jmh-annotationProcessor={ group="org.openjdk.jmh", name="jmh-generator-annprocess", version.ref="jmh" }
testing-jmh-generatorByteCode={ group="org.openjdk.jmh", name="jmh-generator-bytecode", version.ref="jmh" }
testing-testContainers-core= { group="org.testcontainers", name="testcontainers", version.ref="testContainers" }
testing-testContainers-mongodb= { group="org.testcontainers", name="mongodb", version.ref="testContainers" }
testing-testContainers-jupiter= { group="org.testcontainers", name="junit-jupiter", version.ref="testContainers"}
######################################################
## Libraries and plugins only used for the buildScript.
buildScript-plugin-kotlin={ group="org.jetbrains.kotlin", name="kotlin-gradle-plugin", version="1.9.23" }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
package com.mongodb.jbplugin.observability.actions
/**
* A Simple, example action, that prints out in a modal popup the version of the
* connected MongoDB Cluster.
*/

package com.mongodb.jbplugin.actions

import com.intellij.database.dataSource.localDataSource
import com.intellij.database.psi.DbDataSource
Expand All @@ -9,19 +14,24 @@ import com.intellij.openapi.components.Service
import com.intellij.openapi.rd.util.launchChildOnUi
import com.intellij.openapi.ui.Messages
import com.mongodb.jbplugin.accessadapter.datagrip.DataGripBasedReadModelProvider
import com.mongodb.jbplugin.accessadapter.slice.BuildInfoSlice
import com.mongodb.jbplugin.accessadapter.slice.BuildInfo
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch

/**
* Service that implements the action.
*
* @param coroutineScope
*/
@Service(Service.Level.PROJECT)
class GetMongoDBVersionActionService(
class GetMongoDbVersionActionService(
private val coroutineScope: CoroutineScope
) {
fun actionPerformed(event: AnActionEvent) {
coroutineScope.launch {
val readModelProvider = event.project!!.getService(DataGripBasedReadModelProvider::class.java)
val dataSource = event.dataContext.getData(PlatformDataKeys.PSI_ELEMENT) as DbDataSource
val buildInfo = readModelProvider.slice(dataSource.localDataSource!!, BuildInfoSlice)
val buildInfo = readModelProvider.slice(dataSource.localDataSource!!, BuildInfo.Slice)

coroutineScope.launchChildOnUi {
Messages.showMessageDialog(buildInfo.version, "Show DB Version", null)
Expand All @@ -30,8 +40,11 @@ class GetMongoDBVersionActionService(
}
}

class GetMongoDBVersionAction: AnAction() {
/**
* Action that can be run within the contextual menu of a connection in the data explorer.
*/
class GetMongoDbVersionAction : AnAction() {
override fun actionPerformed(event: AnActionEvent) {
event.project!!.getService(GetMongoDBVersionActionService::class.java).actionPerformed(event)
event.project!!.getService(GetMongoDbVersionActionService::class.java).actionPerformed(event)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
</applicationListeners>
<actions>
<action id="com.mongodb.jbplugin.observability.actions.GetMongoDBVersionAction"
class="com.mongodb.jbplugin.observability.actions.GetMongoDBVersionAction" text="Show MongoDB Version">
class="com.mongodb.jbplugin.actions.GetMongoDbVersionAction" text="Show MongoDB Version">
<add-to-group group-id="DatabaseViewPopupMenu" anchor="after" relative-to-action="DatabaseView.Refresh"/>
</action>
</actions>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,53 @@


repositories {
maven("https://www.jetbrains.com/intellij-repository/releases/")
maven("https://packages.jetbrains.team/maven/p/ij/intellij-dependencies")
}

plugins {
alias(libs.plugins.intellij)
}


tasks {
named("test", Test::class) {
environment("TESTCONTAINERS_RYUK_DISABLED", "true")
val homePath = project.layout.buildDirectory.dir("idea-sandbox/config-test").get().asFile.absolutePath

jvmArgs(listOf(
"--add-opens=java.base/java.lang=ALL-UNNAMED",
"--add-opens=java.desktop/java.awt=ALL-UNNAMED",
"--add-opens=java.desktop/javax.swing=ALL-UNNAMED",
"--add-opens=java.desktop/sun.awt=ALL-UNNAMED",
"-Dpolyglot.engine.WarnInterpreterOnly=false",
"-Dpolyglot.log.level=OFF",
"-Didea.home.path=${homePath}"
))
}
}

intellij {
version.set(libs.versions.intellij.min) // Target IDE Version
type.set(libs.versions.intellij.type) // Target IDE Platform

plugins.set(listOf("com.intellij.java", "com.intellij.database"))
}

dependencies {
implementation(libs.gson)
implementation(libs.mongodb.driver)
implementation(project(":packages:mongodb-access-adapter"))

compileOnly(libs.testing.intellij.ideImpl)
compileOnly(libs.testing.intellij.coreUi)
compileOnly("com.jetbrains.intellij.database:database-sql:241.15989.150")
compileOnly("com.jetbrains.intellij.database:database-connectivity:241.15989.150")
compileOnly("com.jetbrains.intellij.database:database-core-impl:241.15989.150") {
exclude("com.jetbrains.fus.reporting", "ap-validation")
testImplementation("com.jetbrains.intellij.platform:test-framework-junit5:241.15989.155") {
exclude("ai.grazie.spell")
exclude("ai.grazie.utils")
exclude("ai.grazie.nlp")
exclude("ai.grazie.model")
exclude("org.jetbrains.teamcity")
}
compileOnly("com.jetbrains.intellij.database:database-jdbc-console:241.15989.150")
compileOnly("com.jetbrains.intellij.database:database:241.15989.150")
compileOnly("com.jetbrains.intellij.platform:images:241.15989.157")
compileOnly("com.jetbrains.intellij.grid:grid-impl:241.15989.150")
compileOnly("com.jetbrains.intellij.grid:grid:241.15989.150")
compileOnly("com.jetbrains.intellij.grid:grid-core-impl:241.15989.150")

testImplementation(libs.testing.testContainers.core)
testImplementation(libs.testing.testContainers.jupiter)
testImplementation(libs.testing.testContainers.mongodb)
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* Represents a service that allows access to a MongoDB cluster
* configured through a DataGrip DataSource.
*/

package com.mongodb.jbplugin.accessadapter.datagrip

import com.intellij.database.dataSource.LocalDataSource
Expand All @@ -6,30 +11,47 @@ import com.intellij.openapi.project.Project
import com.intellij.psi.util.CachedValue
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
import com.mongodb.jbplugin.accessadapter.MongoDBReadModelProvider
import com.mongodb.jbplugin.accessadapter.MongoDbReadModelProvider
import com.mongodb.jbplugin.accessadapter.Slice
import com.mongodb.jbplugin.accessadapter.datagrip.adapter.DataGripMongoDBDriver
import com.mongodb.jbplugin.accessadapter.slice.BuildInfoSlice
import com.mongodb.jbplugin.accessadapter.datagrip.adapter.DataGripMongoDbDriver
import kotlinx.coroutines.runBlocking

private typealias MapOfCachedValues = MutableMap<String, CachedValue<*>>

/**
* The service to be injected to access MongoDB. Usually you will use
* it like this:
*
* ```kt
* val readModelProvider = event.project!!.getService(DataGripBasedReadModelProvider::class.java)
* val dataSource = event.dataContext.getData(PlatformDataKeys.PSI_ELEMENT) as DbDataSource
* val buildInfo = readModelProvider.slice(dataSource.localDataSource!!, BuildInfoSlice)
* ```
*
* It will aggressively cache data at the project level, to avoid hitting MongoDB. Also, the provided
* driver is very slow, so it's better to avoid querying on performance sensitive contexts.
*
* @param project
*/
@Service(Service.Level.PROJECT)
class DataGripBasedReadModelProvider(
private val project: Project,
) : MongoDBReadModelProvider<LocalDataSource> {
private val cachedValues: MutableMap<String, CachedValue<*>> = mutableMapOf()
) : MongoDbReadModelProvider<LocalDataSource> {
private val cachedValues: MapOfCachedValues = mutableMapOf()

override fun <T : Any> slice(dataSource: LocalDataSource, slice: Slice<T>): T {
return cachedValues
.computeIfAbsent(slice.javaClass.canonicalName, fromSlice(dataSource, BuildInfoSlice))
override fun <T : Any> slice(dataSource: LocalDataSource, slice: Slice<T>): T = cachedValues
.computeIfAbsent(slice.javaClass.canonicalName, fromSlice(dataSource, slice))
.value as T
}

private inline fun <reified T : Any> fromSlice(dataSource: LocalDataSource, slice: Slice<T>): (String) -> CachedValue<T> {
private fun <T : Any> fromSlice(
dataSource: LocalDataSource,
slice: Slice<T>
): (String) -> CachedValue<T> {
val cacheManager = CachedValuesManager.getManager(project)
return {
cacheManager.createCachedValue {
runBlocking {
val driver = DataGripMongoDBDriver(project, dataSource)
val driver = DataGripMongoDbDriver(project, dataSource)
val sliceData = slice.queryUsingDriver(driver)

CachedValueProvider.Result.create(sliceData, dataSource)
Expand Down

This file was deleted.

Loading

0 comments on commit c296636

Please sign in to comment.