Conversation
There was a problem hiding this comment.
Pull request overview
This PR extends the Core framework with new infrastructure around config schema migrations, runtime instrumentation (profiling/validation/retry/rate limiting), dependency checks at startup, and persistent cooldown support.
Changes:
- Add a config migration framework and run migrations during startup before config deserialization.
- Introduce new subsystem managers (profiling, validation, retry, rate limiting) with proxy-based interception and expose them via DI.
- Add startup dependency checking and implement persistent cooldown storage/loading.
Reviewed changes
Copilot reviewed 50 out of 51 changed files in this pull request and generated 15 comments.
Show a summary per file
| File | Description |
|---|---|
| src/main/java/dev/mzcy/core/validation/ValidationProxyFactory.java | Adds JDK proxy wrapping for @Validate interception. |
| src/main/java/dev/mzcy/core/validation/ValidationManager.java | Adds validation manager with proxy wrapping + manual validation helpers. |
| src/main/java/dev/mzcy/core/validation/ValidationInterceptor.java | Implements parameter-constraint checking for @Validate. |
| src/main/java/dev/mzcy/core/validation/ValidationException.java | Adds aggregated validation exception type. |
| src/main/java/dev/mzcy/core/validation/constraints/Validate.java | Introduces method-level marker to enable validation. |
| src/main/java/dev/mzcy/core/validation/constraints/Size.java | Adds @Size constraint annotation. |
| src/main/java/dev/mzcy/core/validation/constraints/Range.java | Adds @Range constraint annotation. |
| src/main/java/dev/mzcy/core/validation/constraints/Positive.java | Adds @Positive constraint annotation. |
| src/main/java/dev/mzcy/core/validation/constraints/Pattern.java | Adds @Pattern constraint annotation. |
| src/main/java/dev/mzcy/core/validation/constraints/NotNull.java | Adds @NotNull constraint annotation (custom). |
| src/main/java/dev/mzcy/core/validation/constraints/NotBlank.java | Adds @NotBlank constraint annotation. |
| src/main/java/dev/mzcy/core/validation/constraints/Min.java | Adds @Min constraint annotation. |
| src/main/java/dev/mzcy/core/validation/constraints/Max.java | Adds @Max constraint annotation. |
| src/main/java/dev/mzcy/core/retry/RetryProxyFactory.java | Adds JDK proxy wrapping for @Retry. |
| src/main/java/dev/mzcy/core/retry/RetryManager.java | Adds manager providing proxy wrapping + manual/async retry helpers. |
| src/main/java/dev/mzcy/core/retry/RetryInterceptor.java | Implements retry loop semantics for @Retry calls. |
| src/main/java/dev/mzcy/core/retry/RetryExhaustedException.java | Adds exception for exhausted retry attempts. |
| src/main/java/dev/mzcy/core/retry/Retry.java | Introduces @Retry annotation configuration surface. |
| src/main/java/dev/mzcy/core/retry/BackoffStrategy.java | Adds backoff strategy enum used by retry. |
| src/main/java/dev/mzcy/core/ratelimit/TokenBucket.java | Implements token-bucket limiter primitive. |
| src/main/java/dev/mzcy/core/ratelimit/RateLimitRegistry.java | Adds registry/cache for rate limit buckets and stats. |
| src/main/java/dev/mzcy/core/ratelimit/RateLimitProxyFactory.java | Adds JDK proxy wrapping for @RateLimit. |
| src/main/java/dev/mzcy/core/ratelimit/RateLimitManager.java | Adds manager for rate limiting + manual API + player cleanup listener. |
| src/main/java/dev/mzcy/core/ratelimit/RateLimitInterceptor.java | Implements rate limit enforcement and optional message dispatch. |
| src/main/java/dev/mzcy/core/ratelimit/RateLimit.java | Introduces @RateLimit annotation configuration surface. |
| src/main/java/dev/mzcy/core/profiling/TimingSummary.java | Adds per-key timing aggregation structure. |
| src/main/java/dev/mzcy/core/profiling/TimingRegistry.java | Adds timing registry + query/reset APIs. |
| src/main/java/dev/mzcy/core/profiling/Timed.java | Introduces @Timed annotation configuration surface. |
| src/main/java/dev/mzcy/core/profiling/ProfilingProxyFactory.java | Adds JDK proxy wrapping for @Timed. |
| src/main/java/dev/mzcy/core/profiling/ProfilingManager.java | Adds profiling manager with proxy wrapping + manual timing helpers. |
| src/main/java/dev/mzcy/core/profiling/ProfilingInterceptor.java | Implements timing capture + slow-call warning. |
| src/main/java/dev/mzcy/core/dependency/DependencyPriority.java | Adds dependency priority enum. |
| src/main/java/dev/mzcy/core/dependency/DependencyEntry.java | Adds dependency declarations and factories. |
| src/main/java/dev/mzcy/core/dependency/DependencyCheckResultSet.java | Adds aggregated dependency check results + logging. |
| src/main/java/dev/mzcy/core/dependency/DependencyCheckResult.java | Adds per-dependency check result model. |
| src/main/java/dev/mzcy/core/dependency/DependencyChecker.java | Adds dependency checking with optional version enforcement. |
| src/main/java/dev/mzcy/core/debug/DebugOverlay.java | Adds profiling section and rate limit bucket count to overlay. |
| src/main/java/dev/mzcy/core/debug/DebugCommand.java | Adds /core timings command to dump/reset timing data. |
| src/main/java/dev/mzcy/core/CorePlugin.java | Wires new managers, runs migrations, checks dependencies, loads persistent cooldowns. |
| src/main/java/dev/mzcy/core/cooldown/PersistentCooldownStore.java | Adds file-backed store for persisted cooldown entries. |
| src/main/java/dev/mzcy/core/cooldown/CooldownManager.java | Adds persistence support and refactors cooldown tracking to string keys. |
| src/main/java/dev/mzcy/core/cooldown/CooldownKey.java | Exposes GLOBAL_UUID for use by other components. |
| src/main/java/dev/mzcy/core/cooldown/CooldownEntry.java | Makes cooldown entry serializable for persistence. |
| src/main/java/dev/mzcy/core/config/migration/ConfigVersion.java | Adds @ConfigVersion annotation for schema versioning. |
| src/main/java/dev/mzcy/core/config/migration/ConfigMigrationRunner.java | Adds migration runner that reads/backs up/migrates config files. |
| src/main/java/dev/mzcy/core/config/migration/ConfigMigrationManager.java | Adds manager for registering and executing migrations across configs. |
| src/main/java/dev/mzcy/core/config/migration/ConfigMigration.java | Adds migration interface definition. |
| src/main/java/dev/mzcy/core/command/CommandManager.java | Changes cooldown manager creation to resolve from DI container. |
| src/main/java/dev/mzcy/core/annotation/Cooldown.java | Adds persistent flag to cooldown annotation. |
| gradle.properties | Bumps project version. |
| build.gradle.kts | Adjusts dev build JAR classifier naming to include short SHA. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
Comment on lines
+364
to
+367
| final StringBuilder sb = new StringBuilder(); | ||
| for (final TimingSummary s : slowest) { | ||
| if (!sb.isEmpty()) sb.append("\n"); | ||
| sb.append("<gray>").append(s.getKey()) |
Comment on lines
+84
to
+88
| if (sender.hasPermission("core.cooldown.bypass")) return true; | ||
|
|
||
| final UUID uuid = cooldown.global() | ||
| ? CooldownKey.GLOBAL_UUID | ||
| : (sender instanceof Player p ? p.getUniqueId() : CooldownKey.GLOBAL_UUID); |
Comment on lines
+86
to
+91
| final UUID uuid = cooldown.global() | ||
| ? CooldownKey.GLOBAL_UUID | ||
| : (sender instanceof Player p ? p.getUniqueId() : CooldownKey.GLOBAL_UUID); | ||
|
|
||
| final String entryKey = CooldownKey.of(uuid, key).toString(); | ||
| final CooldownEntry existing = resolveEntry(entryKey); |
Comment on lines
+115
to
+120
| entries.put(entryKey, entry); | ||
|
|
||
| // Persist if annotation requests it | ||
| if (cooldown.persistent() && persistentStore != null) { | ||
| persistentStore.put(entryKey, entry); | ||
| } |
Comment on lines
+59
to
+77
| if (bucket.tryConsume()) { | ||
| return invoker.invoke(); | ||
| } | ||
|
|
||
| // Rate limited — send message if a Player is involved | ||
| if (!annotation.silent()) { | ||
| final Player player = resolvePlayer(args); | ||
| if (player != null) { | ||
| final long waitMs = bucket.millisUntilNextToken(); | ||
| final String msg = annotation.message() | ||
| .replace("<remaining>", formatMs(waitMs)); | ||
| player.sendMessage(MINI.deserialize(msg)); | ||
| } | ||
| } | ||
|
|
||
| log.fine(() -> "[RateLimit] Rejected: " + methodKey | ||
| + " for key: " + bucketKey); | ||
| return null; | ||
| } |
|
|
||
| final String directory = configAnnotation.directory(); | ||
| final String filename = configAnnotation.value() | ||
| + (configAnnotation.format().name().equals("JSON") ? ".json" : ".yml"); |
| this.container = container; | ||
| this.cooldownManager = new CooldownManager(); | ||
| this.cooldownManager = container.resolve(CooldownManager.class); | ||
| container.bindInstance(CooldownManager.class, cooldownManager); |
Comment on lines
+28
to
+37
| @Override | ||
| protected String keyToFileName(@NotNull String key) { | ||
| // Replace colon — not valid in filenames on Windows | ||
| return key.replace(":", "__"); | ||
| } | ||
|
|
||
| @Override | ||
| protected String fileNameToKey(@NotNull String fileName) { | ||
| return fileName.replace("__", ":"); | ||
| } |
Comment on lines
+110
to
+117
| // Read raw data | ||
| final ObjectNode root; | ||
| try { | ||
| root = (ObjectNode) mapper.readTree(filePath.toFile()); | ||
| } catch (IOException ex) { | ||
| throw new ConfigException( | ||
| "Failed to read config for migration: " + filePath, ex); | ||
| } |
Comment on lines
+122
to
+128
| // Reset option | ||
| if (ctx.arg(0).map("reset"::equalsIgnoreCase).orElse(false)) { | ||
| core.getProfilingManager().resetAll(); | ||
| ctx.sendSuccess("Timing stats reset."); | ||
| } else { | ||
| ctx.send("<dark_gray>Tip: <gray>/core timings reset"); | ||
| } |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
This pull request introduces several new framework features and infrastructure improvements to the core plugin, focusing on extensibility, configuration management, and new subsystem managers. The most significant changes include the addition of a config migration framework, new manager classes for cooldowns, rate limiting, retries, and profiling, and an improved dependency check on startup. There are also several supporting updates to plugin initialization and property files.
Config migration infrastructure:
ConfigMigrationinterface andConfigMigrationManagerclass, allowing versioned schema migrations for plugin configs before deserialization. This enables safe, automated upgrades of config files as the schema evolves. (src/main/java/dev/mzcy/core/config/migration/ConfigMigration.java,src/main/java/dev/mzcy/core/config/migration/ConfigMigrationManager.java) [1] [2]CorePlugin.java) [1] [2]Subsystem managers and dependency injection:
CooldownManager), persistent cooldown storage, rate limiting (RateLimitManager), retries (RetryManager), profiling (ProfilingManager), and validation (ValidationManager). These are now instantiated, injected, and exposed via getters inCorePlugin, and registered in the dependency injection container. (CorePlugin.java) [1] [2] [3] [4] [5]CommandManagerto resolve and use the sharedCooldownManagerfrom the container rather than creating its own instance. (CommandManager.java)PersistentCooldownStore, and theCooldownannotation supports a newpersistentproperty. (CorePlugin.java,Cooldown.java) [1] [2]Dependency management and startup sequence:
DependencyCheckerandDependencyCheckResultSet, enforcing required and optional plugin dependencies before proceeding. (CorePlugin.java) [1] [2] [3]Miscellaneous:
gradle.propertiesfrom1.0.1to1.0.2.CorePlugin.java)These changes lay the groundwork for more robust configuration handling, better extensibility, and improved runtime safety in the plugin framework.