Skip to content

Commit 124c956

Browse files
committed
KTOR-8494 DI async support
1 parent b343956 commit 124c956

File tree

8 files changed

+195
-25
lines changed

8 files changed

+195
-25
lines changed

ktor-server/ktor-server-plugins/ktor-server-di/api/ktor-server-di.api

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -210,11 +210,12 @@ public class io/ktor/server/plugins/di/DependencyReflectionJvm : io/ktor/server/
210210
public fun toDependencyKey (Lkotlin/reflect/KParameter;)Lio/ktor/server/plugins/di/DependencyKey;
211211
}
212212

213-
public final class io/ktor/server/plugins/di/DependencyRegistry : io/ktor/server/plugins/di/DependencyProvider, io/ktor/server/plugins/di/DependencyResolver {
214-
public fun <init> (Lio/ktor/server/plugins/di/DependencyProvider;Lio/ktor/server/plugins/di/DependencyMap;Lio/ktor/server/plugins/di/DependencyResolution;Lio/ktor/server/plugins/di/DependencyReflection;)V
213+
public final class io/ktor/server/plugins/di/DependencyRegistry : io/ktor/server/plugins/di/DependencyProvider, io/ktor/server/plugins/di/DependencyResolver, kotlinx/coroutines/CoroutineScope {
214+
public fun <init> (Lio/ktor/server/plugins/di/DependencyProvider;Lio/ktor/server/plugins/di/DependencyMap;Lio/ktor/server/plugins/di/DependencyResolution;Lio/ktor/server/plugins/di/DependencyReflection;Lkotlin/coroutines/CoroutineContext;)V
215215
public final fun cleanup (Lio/ktor/server/plugins/di/DependencyKey;Lkotlin/jvm/functions/Function1;)V
216216
public fun contains (Lio/ktor/server/plugins/di/DependencyKey;)Z
217217
public fun get (Lio/ktor/server/plugins/di/DependencyKey;)Ljava/lang/Object;
218+
public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext;
218219
public fun getDeclarations ()Ljava/util/Map;
219220
public fun getOrPut (Lio/ktor/server/plugins/di/DependencyKey;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object;
220221
public fun getReflection ()Lio/ktor/server/plugins/di/DependencyReflection;
@@ -292,11 +293,12 @@ public final class io/ktor/server/plugins/di/InvalidDependencyReferenceException
292293
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
293294
}
294295

295-
public class io/ktor/server/plugins/di/MapDependencyProvider : io/ktor/server/plugins/di/DependencyProvider {
296+
public class io/ktor/server/plugins/di/MapDependencyProvider : io/ktor/server/plugins/di/DependencyProvider, kotlinx/coroutines/CoroutineScope {
296297
public fun <init> ()V
297-
public fun <init> (Lio/ktor/server/plugins/di/DependencyKeyCovariance;Lio/ktor/server/plugins/di/DependencyConflictPolicy;Lkotlin/jvm/functions/Function1;Lorg/slf4j/Logger;)V
298-
public synthetic fun <init> (Lio/ktor/server/plugins/di/DependencyKeyCovariance;Lio/ktor/server/plugins/di/DependencyConflictPolicy;Lkotlin/jvm/functions/Function1;Lorg/slf4j/Logger;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
298+
public fun <init> (Lio/ktor/server/plugins/di/DependencyKeyCovariance;Lio/ktor/server/plugins/di/DependencyConflictPolicy;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/CoroutineContext;Lorg/slf4j/Logger;)V
299+
public synthetic fun <init> (Lio/ktor/server/plugins/di/DependencyKeyCovariance;Lio/ktor/server/plugins/di/DependencyConflictPolicy;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/CoroutineContext;Lorg/slf4j/Logger;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
299300
public final fun getConflictPolicy ()Lio/ktor/server/plugins/di/DependencyConflictPolicy;
301+
public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext;
300302
public fun getDeclarations ()Ljava/util/Map;
301303
public final fun getKeyMapping ()Lio/ktor/server/plugins/di/DependencyKeyCovariance;
302304
public final fun getOnConflict ()Lkotlin/jvm/functions/Function1;

ktor-server/ktor-server-plugins/ktor-server-di/api/ktor-server-di.klib.api

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -223,9 +223,11 @@ final class io.ktor.server.plugins.di/DependencyMapImpl : io.ktor.server.plugins
223223
final fun contains(io.ktor.server.plugins.di/DependencyKey): kotlin/Boolean // io.ktor.server.plugins.di/DependencyMapImpl.contains|contains(io.ktor.server.plugins.di.DependencyKey){}[0]
224224
}
225225

226-
final class io.ktor.server.plugins.di/DependencyRegistry : io.ktor.server.plugins.di/DependencyProvider, io.ktor.server.plugins.di/DependencyResolver { // io.ktor.server.plugins.di/DependencyRegistry|null[0]
227-
constructor <init>(io.ktor.server.plugins.di/DependencyProvider, io.ktor.server.plugins.di/DependencyMap, io.ktor.server.plugins.di/DependencyResolution, io.ktor.server.plugins.di/DependencyReflection) // io.ktor.server.plugins.di/DependencyRegistry.<init>|<init>(io.ktor.server.plugins.di.DependencyProvider;io.ktor.server.plugins.di.DependencyMap;io.ktor.server.plugins.di.DependencyResolution;io.ktor.server.plugins.di.DependencyReflection){}[0]
226+
final class io.ktor.server.plugins.di/DependencyRegistry : io.ktor.server.plugins.di/DependencyProvider, io.ktor.server.plugins.di/DependencyResolver, kotlinx.coroutines/CoroutineScope { // io.ktor.server.plugins.di/DependencyRegistry|null[0]
227+
constructor <init>(io.ktor.server.plugins.di/DependencyProvider, io.ktor.server.plugins.di/DependencyMap, io.ktor.server.plugins.di/DependencyResolution, io.ktor.server.plugins.di/DependencyReflection, kotlin.coroutines/CoroutineContext) // io.ktor.server.plugins.di/DependencyRegistry.<init>|<init>(io.ktor.server.plugins.di.DependencyProvider;io.ktor.server.plugins.di.DependencyMap;io.ktor.server.plugins.di.DependencyResolution;io.ktor.server.plugins.di.DependencyReflection;kotlin.coroutines.CoroutineContext){}[0]
228228

229+
final val coroutineContext // io.ktor.server.plugins.di/DependencyRegistry.coroutineContext|{}coroutineContext[0]
230+
final fun <get-coroutineContext>(): kotlin.coroutines/CoroutineContext // io.ktor.server.plugins.di/DependencyRegistry.coroutineContext.<get-coroutineContext>|<get-coroutineContext>(){}[0]
229231
final val declarations // io.ktor.server.plugins.di/DependencyRegistry.declarations|{}declarations[0]
230232
final fun <get-declarations>(): kotlin.collections/Map<io.ktor.server.plugins.di/DependencyKey, io.ktor.server.plugins.di/DependencyCreateFunction> // io.ktor.server.plugins.di/DependencyRegistry.declarations.<get-declarations>|<get-declarations>(){}[0]
231233
final val reflection // io.ktor.server.plugins.di/DependencyRegistry.reflection|{}reflection[0]
@@ -237,10 +239,11 @@ final class io.ktor.server.plugins.di/DependencyRegistry : io.ktor.server.plugin
237239
final fun cleanup(io.ktor.server.plugins.di/DependencyKey, kotlin/Function1<kotlin/Any?, kotlin/Unit>) // io.ktor.server.plugins.di/DependencyRegistry.cleanup|cleanup(io.ktor.server.plugins.di.DependencyKey;kotlin.Function1<kotlin.Any?,kotlin.Unit>){}[0]
238240
final fun contains(io.ktor.server.plugins.di/DependencyKey): kotlin/Boolean // io.ktor.server.plugins.di/DependencyRegistry.contains|contains(io.ktor.server.plugins.di.DependencyKey){}[0]
239241
final fun require(io.ktor.server.plugins.di/DependencyKey) // io.ktor.server.plugins.di/DependencyRegistry.require|require(io.ktor.server.plugins.di.DependencyKey){}[0]
240-
final inline fun <#A1: reified kotlin/Any> (io.ktor.server.plugins.di/DependencyProvider).provide(kotlin.reflect/KClass<out #A1>) // io.ktor.server.plugins.di/DependencyRegistry.provide|provide@io.ktor.server.plugins.di.DependencyProvider(kotlin.reflect.KClass<out|0:0>){0§<kotlin.Any>}[0]
242+
final inline fun <#A1: reified kotlin/Any> provide(kotlin.reflect/KClass<out #A1>): io.ktor.server.plugins.di/DependencyRegistry.KeyContext<#A1> // io.ktor.server.plugins.di/DependencyRegistry.provide|provide(kotlin.reflect.KClass<out|0:0>){0§<kotlin.Any>}[0]
241243
final inline fun <#A1: reified kotlin/Any?> cleanup(kotlin/String? = ..., noinline kotlin/Function1<#A1, kotlin/Unit>): io.ktor.server.plugins.di/DependencyRegistry.KeyContext<#A1> // io.ktor.server.plugins.di/DependencyRegistry.cleanup|cleanup(kotlin.String?;kotlin.Function1<0:0,kotlin.Unit>){0§<kotlin.Any?>}[0]
242244
final inline fun <#A1: reified kotlin/Any?> key(kotlin/String? = ..., noinline kotlin/Function1<io.ktor.server.plugins.di/DependencyRegistry.KeyContext<#A1>, kotlin/Unit>): io.ktor.server.plugins.di/DependencyRegistry.KeyContext<#A1> // io.ktor.server.plugins.di/DependencyRegistry.key|key(kotlin.String?;kotlin.Function1<io.ktor.server.plugins.di.DependencyRegistry.KeyContext<0:0>,kotlin.Unit>){0§<kotlin.Any?>}[0]
243245
final inline fun <#A1: reified kotlin/Any?> provide(kotlin/String? = ..., noinline kotlin/Function1<io.ktor.server.plugins.di/DependencyResolver, #A1?>): io.ktor.server.plugins.di/DependencyRegistry.KeyContext<#A1> // io.ktor.server.plugins.di/DependencyRegistry.provide|provide(kotlin.String?;kotlin.Function1<io.ktor.server.plugins.di.DependencyResolver,0:0?>){0§<kotlin.Any?>}[0]
246+
final inline fun <#A1: reified kotlin/Any?> provideAsync(kotlin/String? = ..., noinline kotlin.coroutines/SuspendFunction1<io.ktor.server.plugins.di/DependencyResolver, #A1?>): io.ktor.server.plugins.di/DependencyRegistry.KeyContext<kotlinx.coroutines/Deferred<#A1>> // io.ktor.server.plugins.di/DependencyRegistry.provideAsync|provideAsync(kotlin.String?;kotlin.coroutines.SuspendFunction1<io.ktor.server.plugins.di.DependencyResolver,0:0?>){0§<kotlin.Any?>}[0]
244247
final inline fun <#A1: reified kotlin/Any?> provideDelegate(kotlin/Any?, kotlin.reflect/KProperty<*>): kotlin.properties/ReadOnlyProperty<kotlin/Any?, #A1> // io.ktor.server.plugins.di/DependencyRegistry.provideDelegate|provideDelegate(kotlin.Any?;kotlin.reflect.KProperty<*>){0§<kotlin.Any?>}[0]
245248
final inline fun <#A1: reified kotlin/Any?> resolve(kotlin/String? = ...): #A1 // io.ktor.server.plugins.di/DependencyRegistry.resolve|resolve(kotlin.String?){0§<kotlin.Any?>}[0]
246249

@@ -328,15 +331,17 @@ open class io.ktor.server.plugins.di/DependencyInjectionException : kotlin/Runti
328331
constructor <init>(kotlin/String? = ..., kotlin/Throwable? = ...) // io.ktor.server.plugins.di/DependencyInjectionException.<init>|<init>(kotlin.String?;kotlin.Throwable?){}[0]
329332
}
330333

331-
open class io.ktor.server.plugins.di/MapDependencyProvider : io.ktor.server.plugins.di/DependencyProvider { // io.ktor.server.plugins.di/MapDependencyProvider|null[0]
332-
constructor <init>(io.ktor.server.plugins.di/DependencyKeyCovariance = ..., io.ktor.server.plugins.di/DependencyConflictPolicy = ..., kotlin/Function1<io.ktor.server.plugins.di/DependencyKey, kotlin/Unit> = ..., io.ktor.util.logging/Logger = ...) // io.ktor.server.plugins.di/MapDependencyProvider.<init>|<init>(io.ktor.server.plugins.di.DependencyKeyCovariance;io.ktor.server.plugins.di.DependencyConflictPolicy;kotlin.Function1<io.ktor.server.plugins.di.DependencyKey,kotlin.Unit>;io.ktor.util.logging.Logger){}[0]
334+
open class io.ktor.server.plugins.di/MapDependencyProvider : io.ktor.server.plugins.di/DependencyProvider, kotlinx.coroutines/CoroutineScope { // io.ktor.server.plugins.di/MapDependencyProvider|null[0]
335+
constructor <init>(io.ktor.server.plugins.di/DependencyKeyCovariance = ..., io.ktor.server.plugins.di/DependencyConflictPolicy = ..., kotlin/Function1<io.ktor.server.plugins.di/DependencyKey, kotlin/Unit> = ..., kotlin.coroutines/CoroutineContext = ..., io.ktor.util.logging/Logger = ...) // io.ktor.server.plugins.di/MapDependencyProvider.<init>|<init>(io.ktor.server.plugins.di.DependencyKeyCovariance;io.ktor.server.plugins.di.DependencyConflictPolicy;kotlin.Function1<io.ktor.server.plugins.di.DependencyKey,kotlin.Unit>;kotlin.coroutines.CoroutineContext;io.ktor.util.logging.Logger){}[0]
333336

334337
final val conflictPolicy // io.ktor.server.plugins.di/MapDependencyProvider.conflictPolicy|{}conflictPolicy[0]
335338
final fun <get-conflictPolicy>(): io.ktor.server.plugins.di/DependencyConflictPolicy // io.ktor.server.plugins.di/MapDependencyProvider.conflictPolicy.<get-conflictPolicy>|<get-conflictPolicy>(){}[0]
336339
final val keyMapping // io.ktor.server.plugins.di/MapDependencyProvider.keyMapping|{}keyMapping[0]
337340
final fun <get-keyMapping>(): io.ktor.server.plugins.di/DependencyKeyCovariance // io.ktor.server.plugins.di/MapDependencyProvider.keyMapping.<get-keyMapping>|<get-keyMapping>(){}[0]
338341
final val onConflict // io.ktor.server.plugins.di/MapDependencyProvider.onConflict|{}onConflict[0]
339342
final fun <get-onConflict>(): kotlin/Function1<io.ktor.server.plugins.di/DependencyKey, kotlin/Unit> // io.ktor.server.plugins.di/MapDependencyProvider.onConflict.<get-onConflict>|<get-onConflict>(){}[0]
343+
open val coroutineContext // io.ktor.server.plugins.di/MapDependencyProvider.coroutineContext|{}coroutineContext[0]
344+
open fun <get-coroutineContext>(): kotlin.coroutines/CoroutineContext // io.ktor.server.plugins.di/MapDependencyProvider.coroutineContext.<get-coroutineContext>|<get-coroutineContext>(){}[0]
340345
open val declarations // io.ktor.server.plugins.di/MapDependencyProvider.declarations|{}declarations[0]
341346
open fun <get-declarations>(): kotlin.collections/Map<io.ktor.server.plugins.di/DependencyKey, io.ktor.server.plugins.di/DependencyCreateFunction> // io.ktor.server.plugins.di/MapDependencyProvider.declarations.<get-declarations>|<get-declarations>(){}[0]
342347

@@ -394,3 +399,4 @@ final inline fun <#A: reified kotlin/Any> (io.ktor.server.plugins.di/DependencyR
394399
final inline fun <#A: reified kotlin/Any?> (io.ktor.server.plugins.di/DependencyMap).io.ktor.server.plugins.di/resolve(kotlin/String? = ...): #A // io.ktor.server.plugins.di/resolve|[email protected](kotlin.String?){0§<kotlin.Any?>}[0]
395400
final inline fun <#A: reified kotlin/Any?> (io.ktor.server.plugins.di/DependencyProvider).io.ktor.server.plugins.di/provide(kotlin/String? = ..., noinline kotlin/Function1<io.ktor.server.plugins.di/DependencyResolver, #A?>) // io.ktor.server.plugins.di/provide|[email protected](kotlin.String?;kotlin.Function1<io.ktor.server.plugins.di.DependencyResolver,0:0?>){0§<kotlin.Any?>}[0]
396401
final inline fun <#A: reified kotlin/Any?> io.ktor.server.plugins.di/DependencyKey(kotlin/String? = ..., kotlin/Any? = ...): io.ktor.server.plugins.di/DependencyKey // io.ktor.server.plugins.di/DependencyKey|DependencyKey(kotlin.String?;kotlin.Any?){0§<kotlin.Any?>}[0]
402+
final suspend inline fun <#A: reified kotlin/Any?> (io.ktor.server.plugins.di/DependencyMap).io.ktor.server.plugins.di/resolveAwait(kotlin/String? = ...): #A // io.ktor.server.plugins.di/resolveAwait|[email protected](kotlin.String?){0§<kotlin.Any?>}[0]

ktor-server/ktor-server-plugins/ktor-server-di/common/src/io/ktor/server/plugins/di/DependencyInjection.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import io.ktor.server.application.*
88
import io.ktor.server.plugins.di.utils.*
99
import io.ktor.util.*
1010
import io.ktor.util.reflect.*
11+
import kotlinx.coroutines.Dispatchers
12+
import kotlinx.coroutines.cancel
1113
import kotlin.reflect.KClass
1214

1315
/**
@@ -74,6 +76,7 @@ public val DI: ApplicationPlugin<DependencyInjectionConfig> =
7476
dependenciesMap,
7577
pluginConfig.resolution,
7678
pluginConfig.reflection,
79+
application.coroutineContext + Dispatchers.Default.limitedParallelism(1),
7780
)
7881

7982
with(application) {
@@ -84,7 +87,7 @@ public val DI: ApplicationPlugin<DependencyInjectionConfig> =
8487
val exceptions = mutableListOf<Pair<DependencyKey, Throwable>>()
8588
for ((key, source) in registry.requirements) {
8689
try {
87-
registry.get<Any>(key)
90+
registry.get<Any?>(key)
8891
} catch (e: Throwable) {
8992
environment.log.error("Cannot resolve $key\n${source.externalTrace()}")
9093
exceptions += key to e
@@ -117,6 +120,7 @@ public val DI: ApplicationPlugin<DependencyInjectionConfig> =
117120
environment.log.error("Exception during cleanup for $key; continuing", e)
118121
}
119122
}
123+
registry.cancel()
120124
}
121125

122126
attributes.put(DependencyRegistryKey, registry)

ktor-server/ktor-server-plugins/ktor-server-di/common/src/io/ktor/server/plugins/di/DependencyProvider.kt

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,11 @@
44

55
package io.ktor.server.plugins.di
66

7-
import io.ktor.server.plugins.di.DependencyConflictResult.Ambiguous
8-
import io.ktor.server.plugins.di.DependencyConflictResult.Conflict
9-
import io.ktor.server.plugins.di.DependencyConflictResult.KeepNew
10-
import io.ktor.server.plugins.di.DependencyConflictResult.KeepPrevious
11-
import io.ktor.server.plugins.di.DependencyConflictResult.Replace
12-
import io.ktor.util.logging.KtorSimpleLogger
13-
import io.ktor.util.logging.Logger
14-
import io.ktor.util.logging.debug
15-
import io.ktor.util.logging.trace
7+
import io.ktor.server.plugins.di.DependencyConflictResult.*
8+
import io.ktor.util.logging.*
9+
import kotlinx.coroutines.CoroutineScope
10+
import kotlinx.coroutines.Dispatchers
11+
import kotlin.coroutines.CoroutineContext
1612

1713
/**
1814
* Represents a provider for managing dependencies in a dependency injection mechanism.
@@ -189,14 +185,23 @@ public fun <T> DependencyCreateFunction.ifImplicit(block: (ImplicitCreateFunctio
189185
* for the same dependency key.
190186
* @param onConflict A callback that is invoked when a conflict is encountered during registration.
191187
* By default, this throws a `DuplicateDependencyException`.
188+
* @param coroutineContext The coroutine context used for asynchronous dependency resolution.
189+
* By default, this uses a single-threaded dispatcher to avoid concurrency problems.
190+
* @param log A logger used for logging dependency resolution events.
191+
* By default, this uses a `KtorSimpleLogger` with the name "io.ktor.server.plugins.di.MapDependencyProvider".
192+
*
193+
* @see DependencyKeyCovariance
194+
* @see DependencyConflictPolicy
195+
* @see DependencyResolver
192196
*/
193197
@Suppress("UNCHECKED_CAST")
194198
public open class MapDependencyProvider(
195199
public val keyMapping: DependencyKeyCovariance = DefaultKeyCovariance,
196200
public val conflictPolicy: DependencyConflictPolicy = DefaultConflictPolicy,
197201
public val onConflict: (DependencyKey) -> Unit = { throw DuplicateDependencyException(it) },
202+
public override val coroutineContext: CoroutineContext = Dispatchers.Default.limitedParallelism(1),
198203
private val log: Logger = KtorSimpleLogger("io.ktor.server.plugins.di.MapDependencyProvider"),
199-
) : DependencyProvider {
204+
) : DependencyProvider, CoroutineScope {
200205
private companion object {
201206
private const val COVARIANT_LOG_LIMIT = 8
202207
}

0 commit comments

Comments
 (0)