-
-
Notifications
You must be signed in to change notification settings - Fork 5
Add hot restarting #232
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
freya022
wants to merge
11
commits into
3.X
Choose a base branch
from
feature/restarter
base: 3.X
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Add hot restarting #232
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
6a54e56
Added an internal application start event
freya022 fb53316
Add restarter module
freya022 880b840
Add implementation of RestartClassLoaderAdapterFactory
freya022 5bd2e63
test-bot: Use restarter module
freya022 0882e7d
Remove unused code
freya022 d215a82
Rename config file
freya022 164da30
Add README.md
freya022 c3e3691
Clear cache of method accessors on restart
freya022 3f2bbca
Update config
freya022 9a858e6
Add missing badge
freya022 bbda95a
Reset AppEmojisLoader on (re)start
freya022 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 5 additions & 0 deletions
5
...main/kotlin/io/github/freya022/botcommands/internal/core/events/BApplicationStartEvent.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| package io.github.freya022.botcommands.internal.core.events | ||
|
|
||
| import io.github.freya022.botcommands.api.core.config.BConfig | ||
|
|
||
| class BApplicationStartEvent internal constructor(val config: BConfig) |
8 changes: 8 additions & 0 deletions
8
...ain/kotlin/io/github/freya022/botcommands/internal/core/hooks/ApplicationStartListener.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package io.github.freya022.botcommands.internal.core.hooks | ||
|
|
||
| import io.github.freya022.botcommands.internal.core.events.BApplicationStartEvent | ||
|
|
||
| interface ApplicationStartListener { | ||
|
|
||
| fun onApplicationStart(event: BApplicationStartEvent) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| [bc-module-maven-central-shield]: https://img.shields.io/maven-central/v/io.github.freya022/BotCommands-restarter?label=Maven%20central&logo=apachemaven&versionPrefix=3 | ||
| [bc-module-maven-central-link]: https://central.sonatype.com/artifact/io.github.freya022/BotCommands-restarter | ||
|
|
||
| # BotCommands module - Hot restarter | ||
| This module enables fast restarts of your bot as you develop it. | ||
|
|
||
| When you build changes of your code, it restarts automatically, in the same JVM, | ||
| leading to much faster restarts, as it doesn't need to recompile most of the code. | ||
|
|
||
| > [!WARNING] | ||
| > If you are using Spring, use [`spring-boot-devtools`](https://docs.spring.io/spring-boot/reference/using/devtools.html) instead. | ||
|
|
||
| ## Installing | ||
| [![BotCommands-restarter on maven central][bc-module-maven-central-shield] ][bc-module-maven-central-link] | ||
|
|
||
| ### Maven | ||
| ```xml | ||
| <dependencies> | ||
| <dependency> | ||
| <groupId>io.github.freya022</groupId> | ||
| <artifactId>BotCommands-restarter</artifactId> | ||
| <version>VERSION</version> | ||
| </dependency> | ||
| </dependencies> | ||
| ``` | ||
|
|
||
| ### Gradle | ||
| ```gradle | ||
| repositories { | ||
| mavenCentral() | ||
| } | ||
|
|
||
| dependencies { | ||
| implementation("io.github.freya022:BotCommands-restarter:VERSION") | ||
| } | ||
| ``` | ||
|
|
||
| ### Snapshots | ||
|
|
||
| To use the latest, unreleased changes, see [SNAPSHOTS.md](../SNAPSHOTS.md). | ||
|
|
||
| ## Usage | ||
| You can enable the feature by doing so, after which, every build will restart your application. | ||
|
|
||
| ### Kotlin | ||
| ```kotlin | ||
| fun main(args: Array<out String>) { | ||
| // ... | ||
| BotCommands.create { | ||
| // ... | ||
|
|
||
| @OptIn(ExperimentalRestartApi::class) | ||
| registerRestarter(args) { | ||
| // Optional configuration | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ### Java | ||
| ```java | ||
| void main(String[] args) { | ||
| // ... | ||
| BotCommands.create(config -> { | ||
| // ... | ||
|
|
||
| var restarterConfig = RestarterConfig.builder(args) | ||
| // Optional configuration | ||
| .build(); | ||
| config.registerModule(restarterConfig); | ||
| }); | ||
| } | ||
| ``` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| import dev.freya02.botcommands.plugins.configureJarArtifact | ||
|
|
||
| plugins { | ||
| id("repositories-conventions") | ||
| id("kotlin-conventions") | ||
| id("publish-conventions") | ||
| id("dokka-conventions") | ||
| } | ||
|
|
||
| dependencies { | ||
| api(projects.botCommandsCore) | ||
|
|
||
| // Logging | ||
| implementation(libs.kotlin.logging) | ||
| } | ||
|
|
||
| kotlin { | ||
| compilerOptions { | ||
| freeCompilerArgs.addAll( | ||
| "-opt-in=dev.freya02.botcommands.restarter.api.ExperimentalRestartApi", | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| publishedProjectEnvironment { | ||
| configureJarArtifact( | ||
| artifactId = "BotCommands-restarter", | ||
| description = "Enables restarting your bot on the same JVM during development.", | ||
| url = "https://github.com/freya022/BotCommands/tree/3.X/BotCommands-restarter", | ||
| ) | ||
| } |
17 changes: 17 additions & 0 deletions
17
...restarter/src/main/kotlin/dev/freya02/botcommands/restarter/api/ExperimentalRestartApi.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| package dev.freya02.botcommands.restarter.api | ||
|
|
||
| /** | ||
| * Opt-in marker annotation for the hot restart feature. | ||
| * | ||
| * This feature provides no guarantee and its API may change (including removals) at any time. | ||
| * | ||
| * Please create an issue if you encounter a problem, including if it needs adaptations for your use case. | ||
| */ | ||
| @RequiresOptIn( | ||
| message = "This feature is experimental, please see the documentation of this opt-in annotation (@ExperimentalRestartApi) for more details.", | ||
| level = RequiresOptIn.Level.ERROR | ||
| ) | ||
| @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.PROPERTY_SETTER) | ||
| @Retention(AnnotationRetention.BINARY) | ||
| @MustBeDocumented | ||
| annotation class ExperimentalRestartApi |
128 changes: 128 additions & 0 deletions
128
...restarter/src/main/kotlin/dev/freya02/botcommands/restarter/api/config/RestarterConfig.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,128 @@ | ||
| package dev.freya02.botcommands.restarter.api.config | ||
|
|
||
| import dev.freya02.botcommands.restarter.api.ExperimentalRestartApi | ||
| import dev.freya02.botcommands.restarter.internal.exceptions.throwInternal | ||
| import io.github.freya022.botcommands.api.core.config.BConfig | ||
| import io.github.freya022.botcommands.api.core.config.BConfigBuilder | ||
| import io.github.freya022.botcommands.api.core.config.IConfig | ||
| import io.github.freya022.botcommands.api.core.config.getConfigOrNull | ||
| import io.github.freya022.botcommands.api.core.service.annotations.InjectedService | ||
| import io.github.freya022.botcommands.internal.core.config.ConfigDSL | ||
| import java.time.Duration as JavaDuration | ||
| import kotlin.time.Duration | ||
| import kotlin.time.Duration.Companion.seconds | ||
| import kotlin.time.toJavaDuration | ||
| import kotlin.time.toKotlinDuration | ||
|
|
||
| @ExperimentalRestartApi | ||
| interface RestarterConfigProps { | ||
|
|
||
| /** | ||
| * The program arguments passed to the main function upon restarting. | ||
| */ | ||
| val startArgs: List<String> | ||
|
|
||
| /** | ||
| * The time to wait before assuming all changes were compiled, | ||
| * so the application can be restarted with the new changes. | ||
| * | ||
| * Default: 1 second | ||
| */ | ||
| val restartDelay: Duration | ||
|
|
||
| /** | ||
| * Returns the time to wait before assuming all changes were compiled, | ||
| * so the application can be restarted with the new changes. | ||
| * | ||
| * Default: 1 second | ||
| */ | ||
| fun getRestartDelay(): JavaDuration = restartDelay.toJavaDuration() | ||
| } | ||
|
|
||
| /** | ||
| * Configuration for the restarter feature. | ||
| * | ||
| * To enable this feature, a configuration of it must be registered. | ||
| * | ||
| * @see [RestarterConfig.builder] | ||
| * @see [registerRestarter] | ||
| */ | ||
| @InjectedService | ||
| @ExperimentalRestartApi | ||
| interface RestarterConfig : IConfig, RestarterConfigProps { | ||
|
|
||
| override val configType get() = RestarterConfig::class.java | ||
|
|
||
| companion object { | ||
| /** | ||
| * Creates a new [RestarterConfigBuilder], you must [build] it and [register][BConfigBuilder.registerModule] it. | ||
| * | ||
| * @param args The program arguments, they will be passed to the main method upon restarting | ||
| */ | ||
| fun builder(args: Array<out String>): RestarterConfigBuilder { | ||
| return RestarterConfigBuilder.create(args) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @ExperimentalRestartApi | ||
| internal val BConfig.restarterConfig: RestarterConfig | ||
| get() = getConfigOrNull<RestarterConfig>() | ||
| ?: throwInternal("Attempted to fetch a configuration of a disabled feature") | ||
|
|
||
| /** | ||
| * Builder of [RestarterConfig]. | ||
| * | ||
| * @see [RestarterConfigBuilder.Companion.create] | ||
| */ | ||
| @ConfigDSL | ||
| @ExperimentalRestartApi | ||
| class RestarterConfigBuilder private constructor( | ||
| override val startArgs: List<String>, | ||
| ) : RestarterConfigProps { | ||
|
|
||
| override var restartDelay: Duration = 1.seconds | ||
|
|
||
| /** | ||
| * Sets the time to wait before assuming all changes were compiled, | ||
| * so the application can be restarted with the new changes. | ||
| * | ||
| * Default: 1 second | ||
| */ | ||
| fun setRestartDelay(delay: JavaDuration): RestarterConfigBuilder { | ||
| this.restartDelay = delay.toKotlinDuration() | ||
| return this | ||
| } | ||
|
|
||
| /** | ||
| * Builds the [RestarterConfig], you can register the built configuration with [BConfigBuilder.registerModule]. | ||
| */ | ||
| fun build(): RestarterConfig = object : RestarterConfig { | ||
| override val startArgs = this@RestarterConfigBuilder.startArgs | ||
| override val restartDelay = this@RestarterConfigBuilder.restartDelay | ||
| } | ||
|
|
||
| internal companion object { | ||
|
|
||
| @JvmSynthetic | ||
| internal fun create(args: Array<out String>): RestarterConfigBuilder { | ||
| return RestarterConfigBuilder(args.toList()) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Registers the restarter module, enabling the feature. | ||
| * | ||
| * @param args The program arguments, they will be passed to the main method upon restarting | ||
| * @param block A block for further configuration | ||
| * | ||
| * @throws IllegalStateException If the module was already registered | ||
| */ | ||
| @ExperimentalRestartApi | ||
| fun BConfigBuilder.registerRestarter(args: Array<out String>, block: RestarterConfigBuilder.() -> Unit = { }) { | ||
| val config = RestarterConfigBuilder.create(args) | ||
| .apply(block) | ||
| .build() | ||
| registerModule(config) | ||
| } |
21 changes: 21 additions & 0 deletions
21
...n/kotlin/dev/freya02/botcommands/restarter/internal/BCRestartClassLoaderAdapterFactory.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package dev.freya02.botcommands.restarter.internal | ||
|
|
||
| import io.github.freya022.botcommands.internal.core.restarter.RestartClassLoaderAdapter | ||
| import io.github.freya022.botcommands.internal.core.restarter.RestartClassLoaderAdapterFactory | ||
|
|
||
| internal class BCRestartClassLoaderAdapterFactory : RestartClassLoaderAdapterFactory { | ||
|
|
||
| override fun wrapOrNull(loader: ClassLoader): RestartClassLoaderAdapter? { | ||
| return if (loader is RestartClassLoader) { | ||
| BCRestartClassLoaderAdapter(loader) | ||
| } else { | ||
| null | ||
| } | ||
| } | ||
|
|
||
| private class BCRestartClassLoaderAdapter(private val loader: RestartClassLoader) : RestartClassLoaderAdapter { | ||
|
|
||
| override fun publicDefineClass(name: String, bytes: ByteArray): Class<*> = | ||
| loader.publicDefineClass(name, bytes) | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add maven central badge