Skip to content

Commit

Permalink
Version 1.3.0 (#2)
Browse files Browse the repository at this point in the history
* Set theme jekyll-theme-midnight

* Changed CI release pipeline

* Set theme jekyll-theme-midnight

* Create README.md

* Updated README.md

* Update issue templates

* Fixed gradle dependency issue

* Added ktor-jooq
Fixed incorrect package names

* Jooq DAO provider

* Support Routing scope for jooq

* Bump version 1.3.0
  • Loading branch information
paslavsky authored Jan 17, 2020
1 parent f5430e1 commit d3d6df4
Show file tree
Hide file tree
Showing 13 changed files with 297 additions and 10 deletions.
4 changes: 2 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ plugins {
}

group = "net.paslavsky"
version = "1.2.6-1"
version = "1.3.0"

val ktor_version: String by project

Expand All @@ -27,7 +27,7 @@ subprojects {
}

group = "net.paslavsky"
version = "1.2.6-1"
version = "1.3.0"

repositories {
mavenCentral()
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
kotlin.code.style=official
ktor_version=1.2.6
ktor_version=1.3.0
2 changes: 1 addition & 1 deletion ktor-elastic/src/main/kotlin/ElasticFeature.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package net.paslavsky.ktor.sql
package net.paslavsky.ktor.elastic

import io.ktor.application.*
import io.ktor.util.AttributeKey
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package net.paslavsky.ktor.sql
package net.paslavsky.ktor.elastic

import io.ktor.application.Application
import io.ktor.util.AttributeKey
Expand Down
2 changes: 1 addition & 1 deletion ktor-flyway/src/main/kotlin/FlywayFeature.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package net.paslavsky.ktor.sql2o
package net.paslavsky.ktor.flyway

import io.ktor.application.Application
import io.ktor.application.ApplicationEvents
Expand Down
6 changes: 6 additions & 0 deletions ktor-jooq/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
val jooq_version: String by project

dependencies {
api("org.jooq:jooq:$jooq_version")
api(project(":ktor-sql"))
}
1 change: 1 addition & 0 deletions ktor-jooq/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
jooq_version=3.12.3
37 changes: 37 additions & 0 deletions ktor-jooq/src/main/kotlin/DaoFactory.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package net.paslavsky.ktor.jooq

import io.ktor.application.Application
import io.ktor.routing.Routing
import io.ktor.util.AttributeKey
import org.jooq.Configuration
import org.jooq.DSLContext
import java.util.concurrent.ConcurrentHashMap
import kotlin.reflect.KClass
import kotlin.reflect.full.isSuperclassOf

typealias DaoFactory<T> = (daoClass: KClass<T>, context: DSLContext, configuration: Configuration) -> T

val defaultDaoFactory: DaoFactory<*> = { daoClass, context, configuration ->
daoClass.constructors.let { collection ->
collection.firstOrNull {
it.parameters.size == 1 && Configuration::class.isSuperclassOf(it.parameters[0].type.classifier as KClass<*>)
}?.call(configuration) ?: collection.firstOrNull {
it.parameters.size == 1 && DSLContext::class.isSuperclassOf(it.parameters[0].type.classifier as KClass<*>)
}?.call(context) ?: collection.firstOrNull {
it.parameters.isEmpty()
}?.call() ?: throw InstantiationException("Could not create instance of the ${daoClass.qualifiedName}: no suitable constructors")
}
}

val keys = ConcurrentHashMap<KClass<*>, AttributeKey<*>>()

inline fun <reified T : Any> Application.dao(): T {
@Suppress("UNCHECKED_CAST")
val key = keys.computeIfAbsent(T::class) {
AttributeKey<T>("jooq::dao::${T::class.simpleName}")
} as AttributeKey<T>

return attributes.computeIfAbsent(key) { daoFactory(T::class, jooq, jooqConfig) as T }
}

inline fun <reified T : Any> Routing.dao(): T = application.dao()
197 changes: 197 additions & 0 deletions ktor-jooq/src/main/kotlin/JooqFeature.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
package net.paslavsky.ktor.jooq

import io.ktor.application.Application
import io.ktor.application.ApplicationEvents
import io.ktor.application.ApplicationFeature
import io.ktor.application.ApplicationStopPreparing
import io.ktor.util.AttributeKey
import net.paslavsky.ktor.sql.DBClosed
import net.paslavsky.ktor.sql.DBClosing
import net.paslavsky.ktor.sql.DBConnected
import org.jooq.*
import org.jooq.conf.Settings
import org.jooq.impl.DSL
import org.jooq.impl.DefaultConfiguration
import java.time.Clock
import java.util.concurrent.Executor

class JooqFeature private constructor(
pipeline: Application,
monitor: ApplicationEvents,
config: Config
) {
init {
pipeline.attachDaoFactory(config.daoFactory)
monitor.subscribe(DBConnected) { dataSource ->
pipeline.attachJooqContext(
config.configuration.set(dataSource).let {
pipeline.attachJooqConfig(it)
DSL.using(it)
}
)
}
monitor.subscribe(DBClosing) {
try {
pipeline.jooq.close()
} catch (ignore: Exception) {
}
}
monitor.subscribe(DBClosed) {
pipeline.detachJooqConfig()
pipeline.detachJooqContext()
}
monitor.subscribe(ApplicationStopPreparing) {
pipeline.detachDaoFactory()
}
}

class Config(internal val configuration: DefaultConfiguration = DefaultConfiguration()) {
var metaProvider: MetaProvider
get() = configuration.metaProvider()
set(value) {
configuration.set(value)
}

var executor: Executor
get() = configuration.executorProvider().provide()
set(value) {
configuration.set(value)
}

var executorProvider: ExecutorProvider
get() = configuration.executorProvider()
set(value) {
configuration.set(value)
}

var transactionProvider: TransactionProvider
get() = configuration.transactionProvider()
set(value) {
configuration.set(value)
}

var recordMapper: RecordMapper<*, *>
get() = throw NotImplementedError()
set(value) {
configuration.set(value)
}

var recordMapperProvider: RecordMapperProvider
get() = configuration.recordMapperProvider()
set(value) {
configuration.set(value)
}

var recordUnmapper: RecordUnmapper<*, *>
get() = throw NotImplementedError()
set(value) {
configuration.set(value)
}

var recordUnmapperProvider: RecordUnmapperProvider
get() = configuration.recordUnmapperProvider()
set(value) {
configuration.set(value)
}

var recordListeners: Array<RecordListener>
get() = configuration.recordListenerProviders().map { it.provide() }.toTypedArray()
set(value) {
configuration.set(*value)
}

var recordListenerProviders: Array<RecordListenerProvider>
get() = configuration.recordListenerProviders()
set(value) {
configuration.set(*value)
}

var executeListeners: Array<ExecuteListener>
get() = configuration.executeListenerProviders().map { it.provide() }.toTypedArray()
set(value) {
configuration.set(*value)
}

var executeListenerProviders: Array<ExecuteListenerProvider>
get() = configuration.executeListenerProviders()
set(value) {
configuration.set(*value)
}

var visitListeners: Array<VisitListener>
get() = configuration.visitListenerProviders().map { it.provide() }.toTypedArray()
set(value) {
configuration.set(*value)
}

var visitListenerProvider: Array<VisitListenerProvider>
get() = configuration.visitListenerProviders()
set(value) {
configuration.set(*value)
}

var transactionListeners: Array<TransactionListener>
get() = configuration.transactionListenerProviders().map { it.provide() }.toTypedArray()
set(value) {
configuration.set(*value)
}

var transactionListenerProviders: Array<TransactionListenerProvider>
get() = configuration.transactionListenerProviders()
set(value) {
configuration.set(*value)
}

var diagnosticsListeners: Array<DiagnosticsListener>
get() = configuration.diagnosticsListenerProviders().map { it.provide() }.toTypedArray()
set(value) {
configuration.set(*value)
}

var diagnosticsListenerProviders: Array<DiagnosticsListenerProvider>
get() = configuration.diagnosticsListenerProviders()
set(value) {
configuration.set(*value)
}

var unwrapper: Unwrapper
get() = configuration.unwrapperProvider().provide()
set(value) {
configuration.set(value)
}

var unwrapperProvider: UnwrapperProvider
get() = configuration.unwrapperProvider()
set(value) {
configuration.set(value)
}

var clock: Clock
get() = configuration.clock()
set(value) {
configuration.set(value)
}

var dialect: SQLDialect
get() = configuration.dialect()
set(value) {
configuration.set(value)
}

var settings: Settings
get() = configuration.settings()
set(value) {
configuration.set(value)
}

var daoFactory: DaoFactory<*> = defaultDaoFactory
}

companion object Feature : ApplicationFeature<Application, Config, JooqFeature> {
override val key = AttributeKey<JooqFeature>("JooqFeature")

override fun install(pipeline: Application, configure: Config.() -> Unit): JooqFeature {
return JooqFeature(pipeline, pipeline.environment.monitor, Config().apply(configure))
}
}
}
25 changes: 25 additions & 0 deletions ktor-jooq/src/main/kotlin/JooqFields.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package net.paslavsky.ktor.jooq

import io.ktor.application.Application
import io.ktor.routing.Routing
import io.ktor.util.AttributeKey
import org.jooq.Configuration
import org.jooq.DSLContext

private val contextKey = AttributeKey<DSLContext>("jooq::context")
val Application.jooq get() = attributes[contextKey]
inline val Routing.jooq get() = application.jooq
internal fun Application.attachJooqContext(dslContext: DSLContext) = attributes.put(contextKey, dslContext)
internal fun Application.detachJooqContext() = attributes.remove(contextKey)

private val configKey = AttributeKey<Configuration>("jooq::configuration")
val Application.jooqConfig get() = attributes[configKey]
inline val Routing.jooqConfig get() = application.jooqConfig
internal fun Application.attachJooqConfig(configuration: Configuration) = attributes.put(configKey, configuration)
internal fun Application.detachJooqConfig() = attributes.remove(configKey)

private val daoFactoryKey = AttributeKey<DaoFactory<*>>("jooq::daoFactory")
val Application.daoFactory get() = attributes[daoFactoryKey]
inline val Routing.daoFactory get() = application.daoFactory
internal fun Application.attachDaoFactory(daoFactory: DaoFactory<*>) = attributes.put(daoFactoryKey, daoFactory)
internal fun Application.detachDaoFactory() = attributes.remove(daoFactoryKey)
22 changes: 22 additions & 0 deletions ktor-jooq/src/main/kotlin/Transaction.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package net.paslavsky.ktor.jooq

import io.ktor.application.Application
//import org.sql2o.StatementRunnableWithResult
//import org.sql2o.Connection

//enum class TransactionIsolation(internal val value: Int) {
// TRANSACTION_NONE(java.sql.Connection.TRANSACTION_NONE),
// TRANSACTION_READ_UNCOMMITTED(java.sql.Connection.TRANSACTION_READ_UNCOMMITTED),
// TRANSACTION_READ_COMMITTED(java.sql.Connection.TRANSACTION_READ_COMMITTED),
// TRANSACTION_REPEATABLE_READ(java.sql.Connection.TRANSACTION_REPEATABLE_READ),
// TRANSACTION_SERIALIZABLE(java.sql.Connection.TRANSACTION_SERIALIZABLE)
//}
//
//fun <R> Application.transaction(
// isolation: TransactionIsolation = TransactionIsolation.TRANSACTION_READ_COMMITTED,
// block: Connection.() -> R
//) = sql2o.runInTransaction(
// StatementRunnableWithResult<R> { connection, _ -> connection.block() },
// null,
// isolation.value
// ) as R
5 changes: 2 additions & 3 deletions ktor-sql/src/main/kotlin/SqlFeature.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import io.ktor.application.*
import io.ktor.util.AttributeKey
import io.ktor.util.KtorExperimentalAPI
import com.zaxxer.hikari.HikariDataSource
import kotlinx.coroutines.cancel
import org.slf4j.LoggerFactory
import kotlin.system.exitProcess

Expand Down Expand Up @@ -49,7 +48,7 @@ class SqlFeature private constructor(

private fun onStopPreparing(environment: ApplicationEnvironment) {
monitor.raise(DBClosing, dataSource)
if (dataSource.isClosed) {
if (!dataSource.isClosed) {
dataSource.close()
}
pipeline.detachDataSource()
Expand All @@ -61,7 +60,7 @@ class SqlFeature private constructor(

@KtorExperimentalAPI
override fun install(pipeline: Application, configure: Config.() -> Unit): SqlFeature {
val configuration = SqlFeature.Config().apply {
val configuration = Config().apply {
fun prop(name: String) =
pipeline.environment.config.propertyOrNull("dataSource.$name")?.getString()

Expand Down
2 changes: 1 addition & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
rootProject.name = "exktor"
include("ktor-sql", "ktor-consul", "ktor-exposed", "ktor-sql2o", "ktor-flyway", "ktor-elastic")
include("ktor-sql", "ktor-consul", "ktor-exposed", "ktor-sql2o", "ktor-flyway", "ktor-elastic", "ktor-jooq")

0 comments on commit d3d6df4

Please sign in to comment.