Skip to content

Enhance systems with migration, profiling, and rate limiting features#1

Merged
mzcydev merged 12 commits intomasterfrom
dev
Mar 19, 2026
Merged

Enhance systems with migration, profiling, and rate limiting features#1
mzcydev merged 12 commits intomasterfrom
dev

Conversation

@mzcydev
Copy link
Copy Markdown
Owner

@mzcydev mzcydev commented Mar 19, 2026

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:

  • Added a new config migration framework, including the ConfigMigration interface and ConfigMigrationManager class, 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]
  • Integrated config migration into the plugin startup sequence, ensuring migrations run before configs are loaded. (CorePlugin.java) [1] [2]

Subsystem managers and dependency injection:

  • Introduced new manager classes for cooldowns (CooldownManager), persistent cooldown storage, rate limiting (RateLimitManager), retries (RetryManager), profiling (ProfilingManager), and validation (ValidationManager). These are now instantiated, injected, and exposed via getters in CorePlugin, and registered in the dependency injection container. (CorePlugin.java) [1] [2] [3] [4] [5]
  • Updated CommandManager to resolve and use the shared CooldownManager from the container rather than creating its own instance. (CommandManager.java)
  • Added persistent cooldown support: the cooldown manager now loads and saves persistent cooldowns using a PersistentCooldownStore, and the Cooldown annotation supports a new persistent property. (CorePlugin.java, Cooldown.java) [1] [2]

Dependency management and startup sequence:

  • Added a dependency check at plugin startup using a new DependencyChecker and DependencyCheckResultSet, enforcing required and optional plugin dependencies before proceeding. (CorePlugin.java) [1] [2] [3]

Miscellaneous:

  • Updated the plugin version in gradle.properties from 1.0.1 to 1.0.2.
  • Ensured new managers are properly shut down and their state saved on plugin disable. (CorePlugin.java)

These changes lay the groundwork for more robust configuration handling, better extensibility, and improved runtime safety in the plugin framework.

Copilot AI review requested due to automatic review settings March 19, 2026 02:18
@mzcydev mzcydev merged commit 503c379 into master Mar 19, 2026
3 checks passed
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants