Closed gwenneg closed 8 months ago
I'll promote the PR for review when I'm done running some manual tests.
I did NOT keep the old code which prevented the Unleash client from being shut down when Quarkus is reloaded in dev mode: https://github.com/quarkiverse/quarkus-unleash/blob/28f2bc18dd3f9192ff45158ce2a1e739a8277db0/runtime/src/main/java/io/quarkiverse/unleash/runtime/UnleashService.java#L36-L45
@andrejpetras Please let me know if there was a specific reason why that was initially implemented.
@gsmet Does this PR match what you had in mind about the synthetic bean?
I guess this is why the Unleash client should not be shut down in dev mode:
2024-03-04 16:07:10,297 INFO [io.get.rep.FeatureBackupHandlerFile] (Quarkus Main Thread) Unleash will try to load feature toggle states from temporary backup
2024-03-04 16:07:10,300 INFO [io.get.rep.ToggleBootstrapFileProvider] (Quarkus Main Thread) Trying to read feature toggles from bootstrap file found at null
2024-03-04 16:07:10,307 ERROR [io.get.uti.UnleashScheduledExecutorImpl] (Quarkus Main Thread) Unleash background task crashed: java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask@1f2acb49[Not completed, task = java.util.concurrent.Executors$RunnableAdapter@38f0c19b[Wrapped task = io.getunleash.repository.FeatureRepository$$Lambda$1236/0x00000008012ac418@538b5054]] rejected from java.util.concurrent.ScheduledThreadPoolExecutor@35354e61[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 8]
at java.base/java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2065)
at java.base/java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:833)
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor.delayedExecute(ScheduledThreadPoolExecutor.java:340)
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor.scheduleAtFixedRate(ScheduledThreadPoolExecutor.java:632)
at io.getunleash.util.UnleashScheduledExecutorImpl.setInterval(UnleashScheduledExecutorImpl.java:43)
at io.getunleash.repository.FeatureRepository.initCollections(FeatureRepository.java:112)
at io.getunleash.repository.FeatureRepository.<init>(FeatureRepository.java:49)
at io.getunleash.repository.FeatureRepository.<init>(FeatureRepository.java:33)
at io.getunleash.DefaultUnleash.defaultToggleRepository(DefaultUnleash.java:50)
at io.getunleash.DefaultUnleash.<init>(DefaultUnleash.java:54)
at io.quarkiverse.unleash.runtime.UnleashCreator.createUnleash(UnleashCreator.java:31)
at io.quarkiverse.unleash.runtime.UnleashRecorder$1.get(UnleashRecorder.java:31)
at io.quarkiverse.unleash.runtime.UnleashRecorder$1.get(UnleashRecorder.java:28)
at io.quarkus.arc.runtime.ArcRecorder$4.apply(ArcRecorder.java:129)
at io.quarkus.arc.runtime.ArcRecorder$4.apply(ArcRecorder.java:126)
at io.getunleash.Unleash_1dUsziLNibzmhB7vbUKV29eD9C4_Synthetic_Bean.createSynthetic(Unknown Source)
at io.getunleash.Unleash_1dUsziLNibzmhB7vbUKV29eD9C4_Synthetic_Bean.doCreate(Unknown Source)
at io.getunleash.Unleash_1dUsziLNibzmhB7vbUKV29eD9C4_Synthetic_Bean.create(Unknown Source)
at io.getunleash.Unleash_1dUsziLNibzmhB7vbUKV29eD9C4_Synthetic_Bean.create(Unknown Source)
at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:119)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:38)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:35)
at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:32)
at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
at io.quarkus.arc.impl.ComputingCacheContextInstances.computeIfAbsent(ComputingCacheContextInstances.java:19)
at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:35)
at io.getunleash.Unleash_1dUsziLNibzmhB7vbUKV29eD9C4_Synthetic_Bean.get(Unknown Source)
at io.getunleash.Unleash_1dUsziLNibzmhB7vbUKV29eD9C4_Synthetic_Bean.get(Unknown Source)
at io.quarkiverse.unleash.runtime.UnleashLifecycleManager_Observer_onStartup_ADcKH1UFty7zm_hpwYsrbo_EPPY.notify(Unknown Source)
at io.quarkus.arc.impl.EventImpl$Notifier.notifyObservers(EventImpl.java:346)
at io.quarkus.arc.impl.EventImpl$Notifier.notify(EventImpl.java:328)
at io.quarkus.arc.impl.EventImpl.fire(EventImpl.java:82)
at io.quarkus.arc.runtime.ArcRecorder.fireLifecycleEvent(ArcRecorder.java:155)
at io.quarkus.arc.runtime.ArcRecorder.handleLifecycleEvents(ArcRecorder.java:106)
at io.quarkus.deployment.steps.LifecycleEventsBuildStep$startupEvent1144526294.deploy_0(Unknown Source)
at io.quarkus.deployment.steps.LifecycleEventsBuildStep$startupEvent1144526294.deploy(Unknown Source)
at io.quarkus.runner.ApplicationImpl.doStart(Unknown Source)
at io.quarkus.runtime.Application.start(Application.java:101)
at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:111)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:71)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:44)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:124)
at io.quarkus.runner.GeneratedMain.main(Unknown Source)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at io.quarkus.runner.bootstrap.StartupActionImpl$1.run(StartupActionImpl.java:113)
at java.base/java.lang.Thread.run(Thread.java:833)
~The Unleash client should probably use an executor from Quarkus rather than the current one. That's the last thing I'm trying to change before this PR is ready for review.~
Let's deal with that in a subsequent issue/PR: #228.
This is ready for a review now! 🎉
@gwenneg @gsmet
Please let me know if there was a specific reason why that was initially implemented.
That should work. I can't think of any reason why this should be the case
@andrejpetras @gsmet Do you want (or have time) to take another look before I'm merging this PR?
LGTM
Fixes #219. Fixes #223.
This PR introduces
quarkus.unleash.active=true|false
which can be used to disable the extension at run time and is set totrue
by default. In other words, the extension behavior should not change for existing apps after this is merged.