@@ -21,6 +21,7 @@ import com.netflix.graphql.dgs.DgsComponent
2121import com.netflix.graphql.dgs.DgsDataLoaderCustomizer
2222import com.netflix.graphql.dgs.DgsDataLoaderInstrumentation
2323import com.netflix.graphql.dgs.DgsDataLoaderOptionsProvider
24+ import com.netflix.graphql.dgs.DgsDataLoaderReloadController
2425import com.netflix.graphql.dgs.DgsDefaultPreparsedDocumentProvider
2526import com.netflix.graphql.dgs.DgsExecutionResult
2627import com.netflix.graphql.dgs.DgsFederationResolver
@@ -38,6 +39,8 @@ import com.netflix.graphql.dgs.context.GraphQLContextContributorInstrumentation
3839import com.netflix.graphql.dgs.exceptions.DefaultDataFetcherExceptionHandler
3940import com.netflix.graphql.dgs.internal.DataFetcherResultProcessor
4041import com.netflix.graphql.dgs.internal.DefaultDataLoaderOptionsProvider
42+ import com.netflix.graphql.dgs.internal.DefaultDgsDataLoaderProvider
43+ import com.netflix.graphql.dgs.internal.DefaultDgsDataLoaderReloadController
4144import com.netflix.graphql.dgs.internal.DefaultDgsGraphQLContextBuilder
4245import com.netflix.graphql.dgs.internal.DgsDataLoaderInstrumentationDataLoaderCustomizer
4346import com.netflix.graphql.dgs.internal.DgsDataLoaderProvider
@@ -50,6 +53,7 @@ import com.netflix.graphql.dgs.internal.FluxDataFetcherResultProcessor
5053import com.netflix.graphql.dgs.internal.GraphQLJavaErrorInstrumentation
5154import com.netflix.graphql.dgs.internal.MonoDataFetcherResultProcessor
5255import com.netflix.graphql.dgs.internal.QueryValueCustomizer
56+ import com.netflix.graphql.dgs.internal.ReloadableDgsDataLoaderProvider
5357import com.netflix.graphql.dgs.internal.method.ArgumentResolver
5458import com.netflix.graphql.dgs.internal.method.MethodDataFetcherFactory
5559import com.netflix.graphql.dgs.mvc.internal.method.HandlerMethodArgumentResolverAdapter
@@ -61,6 +65,8 @@ import com.netflix.graphql.dgs.springgraphql.DgsGraphQLSourceBuilder
6165import com.netflix.graphql.dgs.springgraphql.ReloadableGraphQLSource
6266import com.netflix.graphql.dgs.springgraphql.SpringGraphQLDgsQueryExecutor
6367import com.netflix.graphql.dgs.springgraphql.SpringGraphQLDgsReactiveQueryExecutor
68+ import com.netflix.graphql.dgs.springgraphql.conditions.ConditionalOnDgsReload
69+ import com.netflix.graphql.dgs.springgraphql.conditions.OnDgsReloadCondition
6470import com.netflix.graphql.dgs.springgraphql.webflux.DgsWebFluxGraphQLInterceptor
6571import com.netflix.graphql.dgs.springgraphql.webmvc.DgsWebMvcGraphQLInterceptor
6672import graphql.GraphQLError
@@ -100,6 +106,7 @@ import org.springframework.boot.system.JavaVersion
100106import org.springframework.context.ApplicationContext
101107import org.springframework.context.annotation.Bean
102108import org.springframework.context.annotation.Configuration
109+ import org.springframework.context.annotation.Primary
103110import org.springframework.core.DefaultParameterNameDiscoverer
104111import org.springframework.core.Ordered
105112import org.springframework.core.PriorityOrdered
@@ -144,7 +151,7 @@ import java.util.function.Consumer
144151import java.util.stream.Collectors
145152
146153/* *
147- * Framework auto configuration based on open source Spring only, without Netflix integrations.
154+ * Framework autoconfiguration based on open source Spring only, without Netflix integrations.
148155 * This does NOT have logging, tracing, metrics and security integration.
149156 */
150157@Suppress(" SpringJavaInjectionPointsAutowiringInspection" )
@@ -221,16 +228,82 @@ open class DgsSpringGraphQLAutoConfiguration(
221228 extensionProviders : List <DataLoaderInstrumentationExtensionProvider >,
222229 customizers : List <DgsDataLoaderCustomizer >,
223230 ): DgsDataLoaderProvider =
224- DgsDataLoaderProvider (
231+ DefaultDgsDataLoaderProvider (
225232 applicationContext = applicationContext,
226233 extensionProviders = extensionProviders,
234+ customizers = customizers,
227235 dataLoaderOptionsProvider = dataloaderOptionProvider,
228236 scheduledExecutorService = dgsScheduledExecutorService,
229237 scheduleDuration = dataloaderConfigProps.scheduleDuration,
230238 enableTickerMode = dataloaderConfigProps.tickerModeEnabled,
231- customizers = customizers,
232239 )
233240
241+ /* *
242+ * Autoconfiguration for DGS Data Loader reloading.
243+ *
244+ * This configuration is only activated when the 'dgs.reload' property is set to `true`.
245+ * It provides the necessary beans for data loader reloading, including:
246+ * - [ReloadableDgsDataLoaderProvider] that wraps the default provider implementation, the [DefaultDgsDataLoaderProvider].
247+ * - An implementation of a [DgsDataLoaderReloadController] that can be used ot force reloading of _Data Loaders_.
248+ *
249+ * **The reloading functionality is designed to be used primarily in development**,
250+ * it is discouraged to be used in production.
251+ */
252+ @AutoConfiguration
253+ @ConditionalOnDgsReload
254+ open class DgsDataLoaderReloadAutoConfiguration (
255+ private val dataloaderConfigProps : DgsDataloaderConfigurationProperties ,
256+ ) {
257+ /* *
258+ * Creates a [ReloadableDgsDataLoaderProvider] that wraps the standard [DgsDataLoaderProvider].
259+ *
260+ * This provider supports dynamic reloading of data loaders based on the [DgsReloadDataLoadersIndicator].
261+ * It maintains the same interface as the standard provider but adds reload capabilities.
262+ *
263+ * The `@Primary` annotation ensures this bean takes precedence over the standard `DgsDataLoaderProvider`
264+ * when reload functionality is enabled.
265+ *
266+ */
267+ @Bean
268+ @Primary
269+ open fun reloadableDgsDataLoaderProvider (
270+ applicationContext : ApplicationContext ,
271+ dataLoaderOptionProvider : DgsDataLoaderOptionsProvider ,
272+ @Qualifier(" dgsScheduledExecutorService" ) dgsScheduledExecutorService : ScheduledExecutorService ,
273+ extensionProviders : List <DataLoaderInstrumentationExtensionProvider >,
274+ customizers : List <DgsDataLoaderCustomizer >,
275+ ): DgsDataLoaderProvider {
276+ LOG .info(" Creating reloadable data loader provider with reload support enabled" )
277+ return ReloadableDgsDataLoaderProvider (
278+ applicationContext = applicationContext,
279+ extensionProviders = extensionProviders,
280+ customizers = customizers,
281+ dataLoaderOptionsProvider = dataLoaderOptionProvider,
282+ scheduledExecutorService = dgsScheduledExecutorService,
283+ scheduleDuration = dataloaderConfigProps.scheduleDuration,
284+ enableTickerMode = dataloaderConfigProps.tickerModeEnabled,
285+ )
286+ }
287+
288+ /* *
289+ * Creates the default data loader reload controller.
290+ *
291+ * This controller provides a programmatic API for triggering data loader reloads
292+ * and accessing reload statistics. It's only available when reload functionality is enabled.
293+ *
294+ * @return DgsDataLoaderReloadController instance
295+ */
296+ @Bean
297+ @ConditionalOnMissingBean
298+ open fun dgsDataLoaderReloadController (
299+ reloadableDgsDataLoaderProvider : ReloadableDgsDataLoaderProvider ,
300+ ): DgsDataLoaderReloadController {
301+ LOG .info(" Creating data loader reload controller" )
302+ // Get the actual ReloadableDgsDataLoaderProvider instance from the context
303+ return DefaultDgsDataLoaderReloadController (reloadableDgsDataLoaderProvider)
304+ }
305+ }
306+
234307 @Bean
235308 open fun entityFetcherRegistry (): EntityFetcherRegistry = EntityFetcherRegistry ()
236309
@@ -272,9 +345,7 @@ open class DgsSpringGraphQLAutoConfiguration(
272345 @Bean
273346 @ConditionalOnMissingBean
274347 open fun defaultReloadSchemaIndicator (environment : Environment ): ReloadSchemaIndicator {
275- val isLaptopProfile = environment.activeProfiles.contains(" laptop" )
276- val hotReloadSetting = environment.getProperty(" dgs.reload" , Boolean ::class .java, isLaptopProfile)
277-
348+ val hotReloadSetting = OnDgsReloadCondition .evaluate(environment)
278349 return ReloadSchemaIndicator {
279350 hotReloadSetting
280351 }
0 commit comments