Skip to content
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

抽离脚本引擎 + 添加 BTN 的脚本支持 #679

Merged
merged 9 commits into from
Nov 3, 2024

Conversation

Ghost-chu
Copy link
Collaborator

@Ghost-chu Ghost-chu commented Nov 3, 2024

Summary by CodeRabbit

Release Notes

  • New Features

    • Integrated a script engine for dynamic rule evaluation.
    • Added support for script-based peer banning rules.
    • Introduced new messaging keys for enhanced clarity in error and status messages related to the rule engine.
  • Bug Fixes

    • Improved error handling and logging during script compilation and execution.
  • Documentation

    • Updated documentation to reflect changes in method signatures and new features related to script handling.
  • Chores

    • Refactored existing code to accommodate the new script engine and improve maintainability.

@Ghost-chu Ghost-chu requested a review from a team as a code owner November 3, 2024 10:53
Copy link
Contributor

coderabbitai bot commented Nov 3, 2024

Walkthrough

This pull request introduces significant enhancements to the PeerBanHelperServer and related classes by integrating a script engine for dynamic rule evaluation. Key modifications include the addition of a ScriptEngine instance across multiple classes, updated constructors, and methods to support script compilation and execution. The changes also involve renaming constants and updating message keys to align with the new rule engine architecture. Overall, these alterations aim to improve the functionality and flexibility of the peer banning system within the application.

Changes

File Path Change Summary
src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java - Added imports for ScriptEngine and related classes.
- Introduced private ScriptEngine scriptEngine.
- Added public ScriptEngine getScriptEngine(), private void setupScriptEngine(), and private void registerFunctions(Class<?> clazz).
- Updated start method.
src/main/java/com/ghostchu/peerbanhelper/btn/BtnConfig.java - Added private ScriptEngine scriptEngine with @Autowired.
- Updated BtnNetwork constructor to include scriptEngine.
- Modified btnNetwork() method to pass scriptEngine.
src/main/java/com/ghostchu/peerbanhelper/btn/BtnNetwork.java - Added private final ScriptEngine scriptEngine.
- Updated constructor to accept ScriptEngine scriptEngine.
- Modified instantiation of BtnAbilityRules to include scriptEngine.
src/main/java/com/ghostchu/peerbanhelper/btn/BtnRule.java - Added private Map<String, String> scriptRules with @SerializedName("script").
src/main/java/com/ghostchu/peerbanhelper/btn/BtnRuleParsed.java - Added private final ScriptEngine scriptEngine.
- Introduced private Map<String, CompiledScript> scriptRules.
- Updated constructor to accept ScriptEngine scriptEngine.
- Added compileScripts method for script compilation.
src/main/java/com/ghostchu/peerbanhelper/btn/ability/BtnAbilityRules.java - Updated constructor to include ScriptEngine scriptEngine.
- Modified loadCacheFile and updateRule methods to instantiate BtnRuleParsed with scriptEngine.
src/main/java/com/ghostchu/peerbanhelper/module/RuleFeatureModule.java - Updated shouldBanPeer method to change parameter from Peer peer to Peer peers.
src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/BtnNetworkOnline.java - Added private ScriptEngine scriptEngine.
- Modified shouldBanPeer to call checkScript.
- Introduced checkScript and runExpression methods for script evaluation.
src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/ExpressionRule.java - Added private ScriptEngine scriptEngine and synchronized list of CompiledScript.
- Updated constructor and methods to utilize new script handling logic.
src/main/java/com/ghostchu/peerbanhelper/scriptengine/CompiledScript.java - Introduced new record class CompiledScript with various properties related to compiled scripts.
src/main/java/com/ghostchu/peerbanhelper/scriptengine/ScriptEngine.java - Enhanced ScriptEngine with methods for handling scripts, including handleResult and compileScript.
- Added constant OK_CHECK_RESULT.
src/main/java/com/ghostchu/peerbanhelper/text/Lang.java - Removed old constants related to module expression rules.
- Added new constants for rule engine-related messages.
src/main/resources/lang/en_us/messages.yml - Renamed keys related to rule engine and expression handling to reflect new terminology.
src/main/resources/lang/messages_fallback.yml - Similar modifications as messages.yml, focusing on renaming and reorganizing keys related to rule engine messages.

Possibly related PRs

  • PCB 作弊快速测试支持 #459: Modifications to the PeerBanHelperServer class, focusing on different functionalities related to peer banning.
  • Webui/torrent #531: Changes to API endpoint access control that may indirectly relate to the application functionality including PeerBanHelperServer.
  • v6.4.0 #544: Introduces support for the BitComet downloader, relevant to the enhancements made in the PeerBanHelperServer.
  • [WebUI] 图形化配置页面 #603: Implements a graphical configuration page in the WebUI, potentially affecting user interaction with the new functionalities.

Suggested reviewers

  • paulzzh

🐇 In the garden, scripts do play,
With rules and logic, they find their way.
A hop, a jump, through code we weave,
In every line, new powers we achieve!
So let us cheer with every change,
For in this world, we boldly range! 🌼


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@paulzzh
Copy link
Collaborator

paulzzh commented Nov 3, 2024

@coderabbitai review

Copy link
Contributor

coderabbitai bot commented Nov 3, 2024

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🧹 Outside diff range and nitpick comments (38)
src/main/java/com/ghostchu/peerbanhelper/module/RunnerAction.java (1)

3-6: LGTM! Consider adding documentation.

The enum implementation is clean and follows Java conventions. However, to improve maintainability and API clarity, consider adding documentation:

 package com.ghostchu.peerbanhelper.module;
 
+/**
+ * Represents the outcome of a peer ban evaluation.
+ * Used by Runner implementations to indicate whether a peer should be banned.
+ *
+ * @since 1.0.0
+ */
 public enum RunnerAction {
+    /**
+     * Indicates that the peer matches ban criteria and should be banned.
+     */
     HIT,
+    /**
+     * Indicates that the peer does not match ban criteria and should not be banned.
+     */
     MISS
 }
src/main/java/com/ghostchu/peerbanhelper/module/impl/pack/IPAddressPack.java (1)

5-8: Add documentation and consider parameter validation.

While the record implementation is clean and appropriate for this use case, consider these improvements:

  1. Add JavaDoc to document the record's purpose and usage
  2. Consider adding validation in the canonical constructor to ensure ipMatcher is not null

Here's a suggested implementation:

+/**
+ * A record that encapsulates an IP address matcher for peer evaluation.
+ * This class is immutable and thread-safe.
+ */
 public record IPAddressPack (
+        /**
+         * The IP matcher used to evaluate IP addresses.
+         * Must not be null.
+         */
         IPMatcher ipMatcher
 ){
+    /**
+     * Creates a new IPAddressPack with the specified IP matcher.
+     *
+     * @param ipMatcher the IP matcher to use (must not be null)
+     * @throws IllegalArgumentException if ipMatcher is null
+     */
+    public IPAddressPack {
+        if (ipMatcher == null) {
+            throw new IllegalArgumentException("ipMatcher must not be null");
+        }
+    }
 }
src/main/java/com/ghostchu/peerbanhelper/module/impl/pack/ClientNamePack.java (1)

8-8: Make the list immutable to prevent modification after construction.

The List<Rule> could be modified after the record is created, potentially leading to unexpected behavior. Consider making it immutable.

-        List<Rule> bannedPeers
+        List<Rule> bannedPeers
+) {
+    public ClientNamePack(List<Rule> bannedPeers) {
+        this.bannedPeers = List.copyOf(bannedPeers); // Creates an unmodifiable copy
+    }
src/main/java/com/ghostchu/peerbanhelper/module/Runner.java (2)

8-8: Remove unused import ExecutorService

The java.util.concurrent.ExecutorService import is not used in this interface.

-import java.util.concurrent.ExecutorService;

10-13: LGTM! Well-designed interface following SOLID principles.

The interface is well-designed with:

  • Clear single responsibility (determining ban actions)
  • Strong null-safety with @NotNull annotations
  • Descriptive method name and parameters

Some architectural considerations:

  1. Consider adding documentation to explain:
    • The contract and expected behavior
    • The significance of the RunnerAction return value
    • Any exceptions that might be thrown
  2. Since this is part of a script engine integration, consider adding a method to validate scripts at load time to fail fast on configuration errors.
src/main/java/com/ghostchu/peerbanhelper/btn/BtnRule.java (1)

25-26: LGTM! Consider adding documentation for script rules.

The new field follows the established pattern of rule storage in the class. However, some documentation would be helpful.

Add Javadoc to describe:

  • Expected format and structure of scripts
  • Valid keys for the Map
  • Example usage
+    /**
+     * Map of script rules where key is the rule identifier and value is the script content.
+     * Scripts are used for dynamic rule evaluation.
+     * Example:
+     * {
+     *   "checkPeer": "script content here"
+     * }
+     */
     @SerializedName("script")
     private Map<String, String> scriptRules;
src/main/java/com/ghostchu/peerbanhelper/module/impl/runner/ClientNameRunner.java (3)

17-17: Remove unused import.

The ExecutorService import is not used in this class.

-import java.util.concurrent.ExecutorService;

23-26: Consider constructor improvements.

  1. The explicit super() call is unnecessary as it's implicitly called.
  2. Consider adding @Autowired annotation for better Spring dependency injection clarity.
+    @Autowired
     public ClientNameRunner(RunnerRegistryManager runnerRegistryManager) {
-        super();
         this.runnerRegistryManager = runnerRegistryManager;
     }

28-36: Consider performance optimizations and monitoring.

To improve the system's scalability and observability, consider:

  1. Caching the rules list with a TTL to reduce registry lookups
  2. Adding metrics to track:
    • Rule match hit/miss ratios
    • Rule matching latency
    • Number of banned clients by rule
  3. Rate limiting rule checks for the same peer/client combination

Would you like me to provide implementation examples for any of these suggestions?

src/main/java/com/ghostchu/peerbanhelper/module/impl/runner/PeerIdRunner.java (2)

16-18: Remove unused imports.

The following imports are not used in the class:

  • java.util.LinkedList
  • java.util.ExecutorService
-import java.util.LinkedList;
-import java.util.ExecutorService;

29-37: Consider adding defensive programming and logging.

The implementation could benefit from the following improvements:

  1. Add null checks despite @NotNull annotations for defensive programming
  2. Add error handling for RuleParser.matchRule
  3. Add logging for ban decisions (especially hits) for audit purposes
  4. Consider caching rule matching results if performance becomes a concern

Here's a suggested improvement:

 @Override
 public @NotNull RunnerAction shouldBanPeer(@NotNull Torrent torrent, @NotNull Peer peer, @NotNull Downloader downloader) {
+    Objects.requireNonNull(peer, "peer cannot be null");
+    String peerId = peer.getPeerId();
+    if (peerId == null) {
+        log.warn("Peer {} has null peerId, skipping rule check", peer);
+        return RunnerAction.MISS;
+    }
+
     List<Rule> ruleList = runnerRegistryManager.get(getClass(), Rule.class);
-    RuleMatchResult matchResult = RuleParser.matchRule(ruleList, peer.getPeerId());
-    if (matchResult.hit()) {
-        return RunnerAction.HIT;
+    try {
+        RuleMatchResult matchResult = RuleParser.matchRule(ruleList, peerId);
+        if (matchResult.hit()) {
+            log.info("Peer {} matched ban rule: {}", peer, matchResult.getMatchedRule());
+            return RunnerAction.HIT;
+        }
+        return RunnerAction.MISS;
+    } catch (Exception e) {
+        log.error("Error matching rules for peer {}: {}", peer, e.getMessage(), e);
+        return RunnerAction.MISS;
     }
-    return RunnerAction.MISS;
 }
src/main/java/com/ghostchu/peerbanhelper/module/impl/registry/RunnerRegistryManager.java (5)

14-14: Consider using more specific generic type bounds.

The registry map's value type List<Supplier<?>> is too broad. Consider using List<Supplier<List<?>>> since all suppliers are expected to return List<Pack>.

-    private final Map<Class<? extends Runner>, List<Supplier<?>>> registry = new ConcurrentHashMap<>();
+    private final Map<Class<? extends Runner>, List<Supplier<List<?>>>> registry = new ConcurrentHashMap<>();

16-19: Utilize or remove the unused description parameter.

The description parameter is not used in the method. Consider either:

  1. Using it for logging when registering suppliers
  2. Removing it if it's not needed

If logging is intended, here's a suggested implementation:

 public <Pack> void register(String description, Class<? extends Runner> clazz, Supplier<List<Pack>> supplier) {
+    log.debug("Registering supplier for runner {}: {}", clazz.getSimpleName(), description);
     List<Supplier<?>> suppliers = registry.computeIfAbsent(clazz, k -> Collections.synchronizedList(new ArrayList<>()));
     suppliers.add(supplier);
 }

21-26: Consider adding logging and return value for unregister operation.

The unregister operation could be more informative by:

  1. Adding debug logging
  2. Returning a boolean to indicate whether the supplier was actually removed
-    public <Pack> void unregister(Class<? extends Runner> clazz, Supplier<List<Pack>> supplier) {
+    public <Pack> boolean unregister(Class<? extends Runner> clazz, Supplier<List<Pack>> supplier) {
         List<Supplier<?>> suppliers = registry.get(clazz);
         if (suppliers != null) {
-            suppliers.remove(supplier);
+            boolean removed = suppliers.remove(supplier);
+            log.debug("Unregistered supplier for runner {}: {}", clazz.getSimpleName(), removed);
+            return removed;
         }
+        return false;
     }

28-30: Add logging and return value for unregisterAll operation.

Similar to the unregister method, consider adding logging and returning the removed suppliers for better observability.

-    public void unregisterAll(Class<? extends Runner> clazz) {
-        registry.remove(clazz);
+    public List<Supplier<?>> unregisterAll(Class<? extends Runner> clazz) {
+        List<Supplier<?>> removed = registry.remove(clazz);
+        log.debug("Unregistered all suppliers for runner {}", clazz.getSimpleName());
+        return removed != null ? removed : Collections.emptyList();
     }

11-13: Add class-level documentation.

Consider adding Javadoc to document:

  1. The purpose of this registry
  2. Thread-safety guarantees
  3. Expected usage patterns
 @Component
 @Slf4j
+/**
+ * A thread-safe registry for managing Runner suppliers.
+ * This class maintains a mapping between Runner classes and their associated suppliers,
+ * allowing dynamic registration and retrieval of Runner-specific configurations.
+ * <p>
+ * All operations are thread-safe, using ConcurrentHashMap for storage and synchronized lists
+ * for supplier collections.
+ */
 public class RunnerRegistryManager {
src/main/java/com/ghostchu/peerbanhelper/btn/ability/BtnAbilityRules.java (2)

43-46: Consider adding null validation for scriptEngine parameter.

While the constructor changes look good, it's recommended to add null validation for the scriptEngine parameter to fail fast if null is passed.

 public BtnAbilityRules(BtnNetwork btnNetwork, ScriptEngine scriptEngine, JsonObject ability) {
+    if (scriptEngine == null) {
+        throw new IllegalArgumentException("scriptEngine cannot be null");
+    }
     this.btnNetwork = btnNetwork;
     this.scriptEngine = scriptEngine;
     this.interval = ability.get("interval").getAsLong();

Line range hint 38-116: Consider documenting the ScriptEngine integration.

The addition of ScriptEngine introduces script execution capabilities to this class. Consider:

  1. Adding class-level documentation explaining the role of ScriptEngine in rule processing
  2. Documenting any script-related requirements or constraints for maintainers
src/main/java/com/ghostchu/peerbanhelper/btn/BtnNetwork.java (1)

112-114: Consider cleaning up commented code.

The commented-out code block for 'submit_hitrate' should either be:

  1. Removed if it's no longer needed
  2. Implemented if it's planned functionality
  3. Documented with a TODO comment explaining why it's commented out
src/main/java/com/ghostchu/peerbanhelper/text/Lang.java (1)

423-423: LGTM! BTN script constants align with requirements.

The BTN script-related constants follow the same pattern as other script-related constants and support the new BTN script functionality.

Consider maintaining alphabetical ordering of enum constants for better maintainability. These constants could be moved near other BTN-related constants.

src/main/resources/lang/messages_fallback.yml (1)

482-482: Add a newline at the end of the file.

YAML files should end with a newline character to follow standard file formatting conventions.

Apply this diff to fix the issue:

 BTN_RULES_SCRIPT_COMPILED: "已成功编译 {} 个脚本,用时 {}ms"
+
🧰 Tools
🪛 yamllint

[error] 482-482: no new line character at the end of file

(new-line-at-end-of-file)

src/main/resources/lang/en_us/messages.yml (1)

266-267: Consider enhancing the return value documentation.

The message clearly lists valid return types but could be more user-friendly.

Consider this improved format:

-  Script {} returned an invalid value. Valid return types are:
-  Boolean: [false=do nothing, true=ban peer]
-  Integer: [0=do nothing, 1=ban peer, 2=skip other rules]
-  com.ghostchu.peerbanhelper.module.PeerAction: [NO_ACTION, BAN, SKIP]
-  com.ghostchu.peerbanhelper.module.BanResult
+  Script {} returned an invalid value. Please return one of these valid types:
+  • Boolean: false (do nothing) or true (ban peer)
+  • Integer: 0 (do nothing), 1 (ban peer), or 2 (skip other rules)
+  • PeerAction enum: NO_ACTION, BAN, or SKIP
+  • BanResult object
src/main/java/com/ghostchu/peerbanhelper/module/impl/runner/IPAddressRunner.java (1)

51-54: Simplify return statement using a ternary operator

You can simplify the return statement for better readability by using a ternary operator.

Apply this diff:

-         if (mr) {
-             return RunnerAction.HIT;
-         }
-         return RunnerAction.MISS;
+         return mr ? RunnerAction.HIT : RunnerAction.MISS;
src/main/java/com/ghostchu/peerbanhelper/btn/BtnRuleParsed.java (4)

36-44: Script compilation in constructor may affect performance

Compiling scripts within the constructor can lead to increased instantiation time, affecting performance, especially if there are many scripts to compile. Consider deferring the compilation to a separate initialization method or performing it asynchronously to improve efficiency.


47-47: Specify initial capacity for HashMap to optimize memory usage

Since the number of scripts is known (scriptRules.size()), initializing the HashMap with an initial capacity can improve performance by reducing the need for resizing.

Apply this diff to set the initial capacity:

-        Map<String, CompiledScript> scripts = new HashMap<>();
+        Map<String, CompiledScript> scripts = new HashMap<>(scriptRules.size());

57-57: Provide more context in error logging

When logging the exception for a failed script compilation, consider including additional information such as the script content or a snippet (if not sensitive) to aid in debugging.


60-60: Consider using System.nanoTime() for more precise timing

Using System.nanoTime() can provide more precise timing measurements compared to System.currentTimeMillis(), which is suitable for profiling the script compilation duration.

Apply this diff to use System.nanoTime():

-        long startAt = System.currentTimeMillis();
+        long startAt = System.nanoTime();

And update the log statement accordingly:

-        log.info(tlUI(Lang.BTN_RULES_SCRIPT_COMPILED, scripts.size(), System.currentTimeMillis() - startAt));
+        log.info(tlUI(Lang.BTN_RULES_SCRIPT_COMPILED, scripts.size(), (System.nanoTime() - startAt) / 1_000_000));
src/main/java/com/ghostchu/peerbanhelper/scriptengine/ScriptEngine.java (2)

26-57: Remove unused commented-out code to improve maintainability

The block of commented-out code from lines 26 to 57 appears to be obsolete. Removing this code will enhance readability and reduce clutter in the codebase.


153-153: Include exception details in log message for better debugging

At line 153, the exception e is caught but not included in the log message. Including the exception in the log will provide stack trace information, aiding in troubleshooting.

Apply this diff to include the exception:

-            log.warn("Script Engine unable to compile the script: {}", fallbackName);
+            log.warn("Script Engine unable to compile the script: {}", fallbackName, e);
src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/ExpressionRule.java (4)

54-54: Consider using a concurrent collection instead of Collections.synchronizedList

Using Collections.synchronizedList can be error-prone as it requires manual synchronization when iterating over the list. To improve thread safety and reduce the risk of concurrent modification issues, consider using a concurrent collection such as CopyOnWriteArrayList.

Apply this change to use a thread-safe collection:

-private final List<CompiledScript> scripts = Collections.synchronizedList(new LinkedList<>());
+private final List<CompiledScript> scripts = new CopyOnWriteArrayList<>();

Line range hint 194-201: Synchronize when iterating over scripts to ensure thread safety

Iteration over a Collections.synchronizedList is not thread-safe unless you manually synchronize on the list. To prevent ConcurrentModificationException and ensure thread safety, wrap the iteration with a synchronized block.

Apply this change to synchronize the iteration:

-public @NotNull CheckResult shouldBanPeer(@NotNull Torrent torrent, @NotNull Peer peer, @NotNull Downloader downloader, @NotNull ExecutorService ruleExecuteExecutor) {
+public @NotNull CheckResult shouldBanPeer(@NotNull Torrent torrent, @NotNull Peer peer, @NotNull Downloader downloader, @NotNull ExecutorService ruleExecuteExecutor) {
+    synchronized (scripts) {
        AtomicReference<CheckResult> checkResult = new AtomicReference<>(pass());
        try (ExecutorService exec = Executors.newVirtualThreadPerTaskExecutor()) {
            for (var compiledScript : scripts) {
                exec.submit(() -> {
                    CheckResult expressionRun = runExpression(compiledScript, torrent, peer, downloader, ruleExecuteExecutor);
                    if (expressionRun.action() == PeerAction.SKIP) {
                        checkResult.set(expressionRun); // Early exit
                        return;
                    }
                    if (expressionRun.action() == PeerAction.BAN) {
                        if (checkResult.get().action() != PeerAction.SKIP) {
                            checkResult.set(expressionRun);
                        }
                    }
                });
            }
        }
        return checkResult.get();
+    }
    }

Line range hint 258-277: Potential concurrent modification of scripts without proper synchronization

The scripts list is being cleared and modified in reloadConfig() which may run concurrently with other threads accessing or iterating over scripts. This can lead to ConcurrentModificationException or inconsistent behavior. Consider synchronizing modifications to scripts or using a thread-safe collection designed for concurrent access.

Apply this change to ensure thread-safe modification:

private void reloadConfig() throws IOException {
+    synchronized (scripts) {
        scripts.clear();
        this.banDuration = getConfig().getLong("ban-duration", 0);
        initScripts();
        log.info(tlUI(Lang.RULE_ENGINE_COMPILING));
        long start = System.currentTimeMillis();
        try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
            File scriptDir = new File(Main.getDataDirectory(), "scripts");
            File[] scripts = scriptDir.listFiles();
            if (scripts != null) {
                for (File script : scripts) {
                    executor.submit(() -> {
                        try {
                            if (!script.getName().endsWith(".av") || script.isHidden()) {
                                return;
                            }
                            try {
                                String scriptContent = java.nio.file.Files.readString(script.toPath(), StandardCharsets.UTF_8);
                                var compiledScript = scriptEngine.compileScript(script, script.getName(), scriptContent);
                                if (compiledScript == null) return;
                                this.scripts.add(compiledScript);
                            } catch (IOException e) {
                                log.error("Unable to load script file", e);
                            }
                        } catch (ExpressionSyntaxErrorException err) {
                            log.error(tlUI(Lang.RULE_ENGINE_BAD_EXPRESSION), err);
                        }
                    });
                }
            }
        }
        getCache().invalidateAll();
        log.info(tlUI(Lang.RULE_ENGINE_COMPILED, scripts.size(), System.currentTimeMillis() - start));
+    }
    }

Line range hint 261-289: Asynchronous script compilation may lead to incomplete initialization

In reloadConfig(), scripts are compiled asynchronously using an ExecutorService, but there is no mechanism to wait for these tasks to complete before proceeding. This can result in scripts not being fully populated when used elsewhere in the application. To ensure that all scripts are compiled before they are needed, consider using executor.shutdown() and executor.awaitTermination() to wait for all tasks to finish.

Apply this change to wait for task completion:

log.info(tlUI(Lang.RULE_ENGINE_COMPILING));
long start = System.currentTimeMillis();
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    // ... existing code to submit tasks ...
+   executor.shutdown();
+   try {
+       if (!executor.awaitTermination(maxScriptExecuteTime, TimeUnit.MILLISECONDS)) {
+           log.warn("Script compilation did not finish within the expected time.");
+       }
+   } catch (InterruptedException e) {
+       log.error("Script compilation was interrupted.", e);
+   }
}
getCache().invalidateAll();
log.info(tlUI(Lang.RULE_ENGINE_COMPILED, scripts.size(), System.currentTimeMillis() - start));
src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/BtnNetworkOnline.java (2)

221-223: Avoid unnecessary synchronization on script.expression()

Synchronizing on script.expression() may introduce a performance bottleneck if multiple scripts are executed concurrently, as it serializes the execution of scripts. If script.expression().execute(env) is thread-safe, consider removing the synchronized block to improve concurrency.

If thread safety is a concern, ensure that each script instance is thread-safe or that appropriate synchronization is applied without impacting overall performance.


225-230: Handle exceptions explicitly and log meaningful messages

Currently, when a TimeoutException or a general Exception occurs, the method returns pass() without notifying the caller. While the error is logged, the calling method might benefit from knowing that an exception occurred during script execution.

Consider propagating exceptions or returning a specific CheckResult indicating an error state. This can help in troubleshooting and provide more transparency to the system's behavior. Additionally, ensure that logged messages include sufficient context to aid in debugging.

src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java (3)

215-216: Remove commented-out code to improve cleanliness.

The commented-out code at lines 215-216 might reduce code clarity and maintainability. Consider removing it if it's no longer needed.

Apply this diff to remove the commented-out code:

-    //        // 表达式允许序列化和反序列化
-    //        AviatorEvaluator.getInstance().setOption(Options.SERIALIZABLE, true);

207-230: Ensure consistency in comment language for better collaboration.

The comments within the setupScriptEngine() method are in Chinese. For better maintainability and collaboration, consider using English for code comments to ensure all team members can understand them.

Apply this diff to translate the comments to English:

-    // ASM 性能优先
+    // Prioritize performance with ASM

-    // EVAL 性能优先
+    // Prioritize performance with EVAL

-    // 降低浮点计算精度
+    // Reduce floating-point calculation precision

-    // 启用变量语法糖
+    // Enable property syntax sugar

-    //        // 表达式允许序列化和反序列化
+    // Allow expression serialization and deserialization

-    // 用户规则写糊保护
+    // Protect against infinite loops in user rules

-    // 启用反射方法查找
+    // Enable reflection method lookup

-    // 注册反射调用
+    // Register reflection calls

38-38: Review package placement for InfoHashUtil.

The InfoHashUtil class is imported from the util.time package. If InfoHashUtil is not related to time utilities, consider moving it to a more appropriate package to improve code organization.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 28cb4b2 and cdf2eb7.

📒 Files selected for processing (24)
  • src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java (6 hunks)
  • src/main/java/com/ghostchu/peerbanhelper/btn/BtnConfig.java (3 hunks)
  • src/main/java/com/ghostchu/peerbanhelper/btn/BtnNetwork.java (4 hunks)
  • src/main/java/com/ghostchu/peerbanhelper/btn/BtnRule.java (1 hunks)
  • src/main/java/com/ghostchu/peerbanhelper/btn/BtnRuleParsed.java (3 hunks)
  • src/main/java/com/ghostchu/peerbanhelper/btn/ability/BtnAbilityRules.java (4 hunks)
  • src/main/java/com/ghostchu/peerbanhelper/module/AbstractRunner.java (1 hunks)
  • src/main/java/com/ghostchu/peerbanhelper/module/RuleFeatureModule.java (1 hunks)
  • src/main/java/com/ghostchu/peerbanhelper/module/Runner.java (1 hunks)
  • src/main/java/com/ghostchu/peerbanhelper/module/RunnerAction.java (1 hunks)
  • src/main/java/com/ghostchu/peerbanhelper/module/impl/pack/ClientNamePack.java (1 hunks)
  • src/main/java/com/ghostchu/peerbanhelper/module/impl/pack/IPAddressPack.java (1 hunks)
  • src/main/java/com/ghostchu/peerbanhelper/module/impl/pack/PeerIdPack.java (1 hunks)
  • src/main/java/com/ghostchu/peerbanhelper/module/impl/registry/RunnerRegistryManager.java (1 hunks)
  • src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/BtnNetworkOnline.java (5 hunks)
  • src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/ExpressionRule.java (8 hunks)
  • src/main/java/com/ghostchu/peerbanhelper/module/impl/runner/ClientNameRunner.java (1 hunks)
  • src/main/java/com/ghostchu/peerbanhelper/module/impl/runner/IPAddressRunner.java (1 hunks)
  • src/main/java/com/ghostchu/peerbanhelper/module/impl/runner/PeerIdRunner.java (1 hunks)
  • src/main/java/com/ghostchu/peerbanhelper/scriptengine/CompiledScript.java (1 hunks)
  • src/main/java/com/ghostchu/peerbanhelper/scriptengine/ScriptEngine.java (1 hunks)
  • src/main/java/com/ghostchu/peerbanhelper/text/Lang.java (2 hunks)
  • src/main/resources/lang/en_us/messages.yml (3 hunks)
  • src/main/resources/lang/messages_fallback.yml (4 hunks)
✅ Files skipped from review due to trivial changes (2)
  • src/main/java/com/ghostchu/peerbanhelper/module/AbstractRunner.java
  • src/main/java/com/ghostchu/peerbanhelper/scriptengine/CompiledScript.java
🧰 Additional context used
🪛 yamllint
src/main/resources/lang/messages_fallback.yml

[error] 482-482: no new line character at the end of file

(new-line-at-end-of-file)

🔇 Additional comments (28)
src/main/java/com/ghostchu/peerbanhelper/module/impl/pack/IPAddressPack.java (1)

1-4: LGTM! Clean package structure and imports.

The package structure follows Java conventions, and the import is specific to the required functionality.

src/main/java/com/ghostchu/peerbanhelper/module/impl/pack/PeerIdPack.java (2)

1-6: LGTM! Clean package structure and imports.

The package structure follows Java conventions, and imports are minimal and specific to the requirements.


3-3: Verify Rule class compatibility and usage patterns.

Let's verify the Rule class implementation and how this record is being used in the codebase.

Also applies to: 8-8

✅ Verification successful

Let me gather more information about the Rule class and its usage pattern.


Let me check the Rule class implementation specifically.


Let me check one final thing about the Rule class itself.


Based on the gathered information, I can now provide the final response:

Import of Rule interface is compatible with the codebase

The Rule interface is a well-defined part of the codebase's rule system, used across various pack implementations including PeerIdPack, ClientNamePack, and IPAddressPack. The import is correctly referencing com.ghostchu.peerbanhelper.util.rule.Rule, which is a valid interface defining the contract for rule matching functionality.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify Rule class implementation and PeerIdPack usage

# Check Rule class implementation
echo "Checking Rule class implementation:"
ast-grep --pattern 'class Rule {
  $$$
}'

# Check how PeerIdPack is being used
echo -e "\nChecking PeerIdPack usage:"
rg -l "PeerIdPack" --type java

# Check for similar pack implementations
echo -e "\nChecking for similar pack implementations:"
fd -e java "Pack.java$"

Length of output: 654


Script:

#!/bin/bash
# Check Rule class content and its usage
echo "Checking Rule class content:"
rg -A 10 "class Rule" --type java

echo -e "\nChecking Rule usage in Pack files:"
for file in $(fd -e java "Pack.java$"); do
    echo -e "\nFile: $file"
    rg "Rule" "$file" -A 3
done

echo -e "\nChecking Rule class imports:"
rg "import.*Rule" --type java

Length of output: 21166


Script:

#!/bin/bash
# Check Rule class implementation
echo "Checking Rule class implementation:"
rg -p "class Rule" --type java -B 2 -A 10

# Check Rule usage in PeerIdPack
echo -e "\nChecking PeerIdPack implementation:"
cat src/main/java/com/ghostchu/peerbanhelper/module/impl/pack/PeerIdPack.java

Length of output: 5403


Script:

#!/bin/bash
# Check Rule class definition
echo "Checking Rule class definition:"
rg -p "class Rule" --type java
rg -p "interface Rule" --type java

# Check Rule.java file if it exists
echo -e "\nChecking Rule.java content:"
fd -e java "Rule.java$" --exec cat {}

Length of output: 19238

src/main/java/com/ghostchu/peerbanhelper/btn/BtnRule.java (1)

25-26: Consider adding script content validation.

Since this field will store executable scripts, consider implementing validation mechanisms.

Let's check if there are any script validation mechanisms in place:

✅ Verification successful

Let's examine the content of the ScriptEngine.java file to understand if there are any validation mechanisms in place.


Let's check the CompiledScript class to fully understand the validation process.


Script validation is already implemented

The codebase already has script validation mechanisms in place:

  • Scripts are validated using AviatorEvaluator.getInstance().validate(scriptContent) before compilation
  • Scripts are compiled using a dedicated script engine (Aviator)
  • Scripts include metadata validation for properties like @name, @author, @Cacheable, @Version, @threadsafe
  • Return value validation is implemented in handleResult method to ensure proper action types
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for script validation or sanitization
rg -l "script.*valid|valid.*script|sanitize.*script|script.*sanitize" 

Length of output: 143


Script:

#!/bin/bash
# Check the content of ScriptEngine.java
cat src/main/java/com/ghostchu/peerbanhelper/scriptengine/ScriptEngine.java

Length of output: 7142


Script:

#!/bin/bash
# Check the content of CompiledScript.java
fd -e java CompiledScript.java -x cat {}

Length of output: 354

src/main/java/com/ghostchu/peerbanhelper/module/RuleFeatureModule.java (1)

8-8: Verify if List import is needed

The java.util.List import appears to be unused in this interface. If it's not needed for the current implementation, consider removing it to keep the imports clean.

src/main/java/com/ghostchu/peerbanhelper/module/impl/runner/PeerIdRunner.java (2)

20-22: LGTM! Well-structured class declaration.

The class follows good practices with proper Spring annotation, immutable field, and clear inheritance hierarchy.


24-27: Verify AbstractRunner's constructor requirements.

The constructor calls super() without parameters. Let's verify that AbstractRunner's no-args constructor is intended to be used.

✅ Verification successful

Let me gather more information about the AbstractRunner class to verify its constructor requirements.


No constructor requirements in AbstractRunner - super() call is appropriate

The AbstractRunner class is a simple abstract class that implements Runner interface and has no explicit constructor. In this case, Java implicitly provides a no-args constructor, making the super() call in PeerIdRunner completely appropriate and correct.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check AbstractRunner's constructor to ensure no-args super() call is appropriate

# Search for AbstractRunner class definition and constructor
ast-grep --pattern 'class AbstractRunner {
  $$$
}'

# Backup: Use ripgrep if ast-grep doesn't find it
rg -A 10 "class AbstractRunner"

Length of output: 282


Script:

#!/bin/bash
# Get the full content of AbstractRunner.java
cat src/main/java/com/ghostchu/peerbanhelper/module/AbstractRunner.java

Length of output: 176

src/main/java/com/ghostchu/peerbanhelper/btn/BtnConfig.java (3)

4-4: LGTM: Clean import addition

The ScriptEngine import is correctly placed and necessary for the new functionality.


26-27: LGTM: Proper dependency injection

The ScriptEngine field is correctly annotated with @Autowired and follows Spring's dependency injection pattern.


37-37: Verify BtnNetwork constructor parameter order

The constructor call looks correct, but since this is a significant change in the constructor signature, let's verify the parameter order matches the BtnNetwork class definition.

✅ Verification successful

Constructor parameter order is correct

The constructor call in BtnConfig.java perfectly matches the parameter order defined in BtnNetwork.java:

// Constructor definition
public BtnNetwork(PeerBanHelperServer server, ScriptEngine scriptEngine, String userAgent, String configUrl, boolean submit, String appId, String appSecret, ModuleMatchCache moduleMatchCache)

// Constructor call
new BtnNetwork(server, scriptEngine, userAgent, configUrl, submit, appId, appSecret, matchCache)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the BtnNetwork constructor parameter order matches the class definition

# Search for the BtnNetwork class constructor definition
ast-grep --pattern 'class BtnNetwork {
  $$$
  BtnNetwork($$$) {
    $$$
  }
  $$$
}'

Length of output: 87


Script:

#!/bin/bash
# Let's try a different approach using ripgrep to find the BtnNetwork constructor
rg "BtnNetwork\(" -A 10 --type java

Length of output: 5434

src/main/java/com/ghostchu/peerbanhelper/btn/ability/BtnAbilityRules.java (3)

8-8: LGTM: Import added for ScriptEngine integration.

The ScriptEngine import is correctly placed and necessary for the new functionality.


38-38: LGTM: ScriptEngine field properly declared.

The field is correctly declared as private final and will be initialized through constructor injection.


61-61: LGTM: Consistent updates to BtnRuleParsed instantiation.

The scriptEngine parameter is consistently passed to BtnRuleParsed in both the cache loading and rule updating code paths.

Also applies to: 116-116

src/main/java/com/ghostchu/peerbanhelper/btn/BtnNetwork.java (4)

6-6: LGTM: Import statement correctly added for ScriptEngine.

The new import is properly placed and follows Java package naming conventions.


39-39: LGTM: ScriptEngine field properly declared.

The field is correctly declared as private and final, following good encapsulation practices.


57-59: LGTM: Constructor properly updated with ScriptEngine parameter.

The constructor changes are well-structured:

  • Logical parameter ordering with core dependencies first
  • Proper field assignment
  • Maintains existing functionality

115-115: Verify BtnAbilityRules implementation with ScriptEngine.

The addition of scriptEngine parameter to BtnAbilityRules instantiation looks correct. However, since this is a significant architectural change:

Let's verify the BtnAbilityRules implementation:

✅ Verification successful

Let me gather more information about BtnAbilityRules specifically.


Let me check the BtnRuleParsed implementation to ensure proper integration.


ScriptEngine integration is properly implemented

The verification shows that:

  • BtnAbilityRules correctly stores and initializes the ScriptEngine parameter
  • It properly passes the ScriptEngine to BtnRuleParsed instances
  • The integration chain (BtnNetwork → BtnAbilityRules → BtnRuleParsed) maintains consistent ScriptEngine usage
  • Error handling is in place across the implementation
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check BtnAbilityRules implementation to ensure it properly handles the ScriptEngine parameter

# Search for BtnAbilityRules class definition and constructor
ast-grep --pattern 'class BtnAbilityRules {
  $$$
  BtnAbilityRules($$$) {
    $$$
  }
  $$$
}'

# Search for any script-related method calls within BtnAbilityRules
rg -A 5 'scriptEngine\.' --type java

Length of output: 3272


Script:

#!/bin/bash
# Search for BtnAbilityRules class implementation
rg -U "class BtnAbilityRules.*?\{.*?\}" --multiline --type java -A 50

# Search for any references to scriptEngine within BtnAbilityRules
rg "scriptEngine" --type java --glob "BtnAbilityRules.java"

Length of output: 839


Script:

#!/bin/bash
# Search for BtnRuleParsed class implementation
rg -U "class BtnRuleParsed.*?\{.*?\}" --multiline --type java -A 50

# Search for ScriptEngine usage in BtnRuleParsed
rg "ScriptEngine" --type java --glob "BtnRuleParsed.java"

Length of output: 494

src/main/java/com/ghostchu/peerbanhelper/text/Lang.java (1)

203-209: LGTM! Rule engine constants are well-structured.

The new rule engine constants follow a consistent naming pattern and appropriately replace the old MODULE_EXPRESSION_RULE_* constants.

src/main/resources/lang/messages_fallback.yml (2)

204-209: LGTM: Script engine messages have been properly renamed and organized.

The renaming from MODULE_EXPRESSION_RULE_* to RULE_ENGINE_* improves clarity and consistency. The new messages provide clear feedback for script compilation, execution, and error states.

Also applies to: 266-267, 311-312


480-482: LGTM: BTN script compilation messages added.

The new messages provide appropriate user feedback during BTN script compilation process.

🧰 Tools
🪛 yamllint

[error] 482-482: no new line character at the end of file

(new-line-at-end-of-file)

src/main/resources/lang/en_us/messages.yml (2)

204-209: LGTM! Clear and informative rule engine messages.

The messages provide good feedback about script compilation, execution, and error states. They cover essential scenarios like syntax errors, compilation progress, timeouts, and runtime errors.


311-312: LGTM! Concise script execution feedback messages.

The messages provide clear feedback about script execution and results.

src/main/java/com/ghostchu/peerbanhelper/btn/BtnRuleParsed.java (3)

15-15: Logging enabled with @Slf4j annotation

The addition of the @Slf4j annotation allows for efficient logging within the class, which is beneficial for monitoring and debugging.


26-26: ScriptEngine integration into BtnRuleParsed

Integrating the ScriptEngine via the scriptEngine field enhances the class's capability to compile and manage scripts dynamically.


52-56: Ensure compileScript handles null context appropriately

Passing null as the first argument to compileScript may lead to unexpected behavior if the method does not handle null values properly. Verify that the compileScript method is designed to accept a null context.

src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/BtnNetworkOnline.java (2)

189-204: Verify the use of Executors.newVirtualThreadPerTaskExecutor()

The use of Executors.newVirtualThreadPerTaskExecutor() introduces virtual threads, which require a Java version that supports Project Loom (Java 19 or later). Ensure that the application's runtime environment is compatible with this feature.

Please confirm that the deployment environment supports virtual threads and that the use of this executor aligns with the project's requirements.


64-65: Confirm the successful injection of ScriptEngine

The scriptEngine is being autowired, but there is no null-check before its usage. If the ScriptEngine bean is not properly configured, this could lead to a NullPointerException.

Ensure that ScriptEngine is correctly defined and initialized in the application context. If there is a possibility of it being null, consider adding a null-check or using @Autowired(required = true) to enforce its presence.

src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java (1)

140-141: ⚠️ Potential issue

Initialize scriptEngine field to prevent potential NullPointerException.

The scriptEngine field is declared but never initialized. This could lead to a NullPointerException if accessed before being set. Ensure that scriptEngine is properly initialized, perhaps in the setupScriptEngine() method.

Run the following script to verify that scriptEngine is initialized and used appropriately:

This script will help you identify whether scriptEngine is being properly initialized and how it's used across the codebase.

@Ghost-chu
Copy link
Collaborator Author

@coderabbitai review

Copy link
Contributor

coderabbitai bot commented Nov 3, 2024

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (3)
src/main/java/com/ghostchu/peerbanhelper/scriptengine/ScriptEngine.java (2)

113-156: Add additional safety checks to script compilation

While the method implements previous review suggestions, there are still some potential issues:

  1. No validation of metadata values (empty strings, malformed values)
  2. Potential infinite loop with empty files
  3. Missing maximum file size check

Consider these improvements:

     @Nullable
     public CompiledScript compileScript(File file, String fallbackName, String scriptContent) {
+        if (scriptContent == null || scriptContent.isEmpty()) {
+            log.warn("Empty script content for: {}", fallbackName);
+            return null;
+        }
+        if (scriptContent.length() > MAX_SCRIPT_SIZE) {
+            log.warn("Script too large: {} ({} bytes)", fallbackName, scriptContent.length());
+            return null;
+        }

         try (BufferedReader reader = new BufferedReader(new StringReader(scriptContent))) {
             String name = fallbackName;
             String author = "Unknown";
             String version = "null";
             boolean cacheable = true;
             boolean threadSafe = true;
+            int lineCount = 0;
             while (true) {
+                if (lineCount++ > MAX_HEADER_LINES) {
+                    log.warn("Too many header lines in script: {}", fallbackName);
+                    break;
+                }
                 String line = reader.readLine();
                 if (line == null) {
                     break;
                 }
                 if (line.startsWith("#")) {
                     line = line.substring(1).trim();
+                    String value;
                     if (line.startsWith("@NAME")) {
-                        name = line.substring(5).trim();
+                        value = line.substring(5).trim();
+                        name = value.isEmpty() ? fallbackName : value;
                     } else if (line.startsWith("@AUTHOR")) {
-                        author = line.substring(7).trim();
+                        value = line.substring(7).trim();
+                        author = value.isEmpty() ? "Unknown" : value;

152-154: Improve error logging for script compilation failures

The current error logging doesn't include the exception details, which could be valuable for debugging script issues.

-            log.warn("Script Engine unable to compile the script: {}", fallbackName);
+            log.warn("Script Engine unable to compile the script: {}", fallbackName, e);
src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/BtnNetworkOnline.java (1)

177-213: Add method documentation and improve error handling.

Consider adding JavaDoc to explain the method's purpose and behavior. Also, the error handling could be enhanced:

  1. The current error handling silently logs errors and continues. Consider if some errors should propagate up.
  2. The thread interruption should be re-interrupted to maintain the interrupt status.
+    /**
+     * Evaluates BTN script rules for the given peer.
+     * 
+     * @param torrent The torrent being checked
+     * @param peer The peer to evaluate
+     * @param downloader The downloader instance
+     * @param ruleExecuteExecutor The executor service
+     * @return CheckResult indicating the evaluation result
+     */
     private @NotNull CheckResult checkScript(Torrent torrent, Peer peer, Downloader downloader, ExecutorService ruleExecuteExecutor) {
         // ... existing code ...
         } catch (InterruptedException | ExecutionException e) {
-            log.error("Error executing script, skipping", e);
+            log.error("Error executing script", e);
+            if (e instanceof InterruptedException) {
+                Thread.currentThread().interrupt();
+            }
         }
         // ... existing code ...
     }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between cdf2eb7 and 4735648.

📒 Files selected for processing (2)
  • src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/BtnNetworkOnline.java (5 hunks)
  • src/main/java/com/ghostchu/peerbanhelper/scriptengine/ScriptEngine.java (1 hunks)
🔇 Additional comments (4)
src/main/java/com/ghostchu/peerbanhelper/scriptengine/ScriptEngine.java (1)

25-57: Consider implementing or removing the commented runExpression method

The commented-out runExpression method appears to be important functionality for executing scripts with proper thread safety and timeout handling. If this is planned functionality, it should be implemented. If it's no longer needed, it should be removed to maintain code clarity.

Let's check if this method is referenced elsewhere:

Would you like assistance in implementing the runExpression method with proper thread safety and timeout handling?

src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/BtnNetworkOnline.java (3)

15-16: LGTM: Script engine integration looks good.

The imports and dependency injection for the script engine are properly configured.

Also applies to: 66-67


170-173: LGTM: Proper integration of script checks.

The script check is correctly placed in the validation chain, with appropriate early return behavior.


215-243: Consider performance optimization and add documentation.

  1. The synchronization on script.expression() could become a bottleneck under high load. Consider using a more granular locking strategy or evaluating if synchronization is necessary.
  2. Add JavaDoc to document the method's behavior, especially regarding caching and error handling.
+    /**
+     * Executes a compiled script with the given context.
+     * Results are cached based on the script's hash code and peer's cache key.
+     * 
+     * @param script The compiled script to execute
+     * @param torrent The torrent context
+     * @param peer The peer being evaluated
+     * @param downloader The downloader instance
+     * @param ruleExecuteExecutor The executor service
+     * @return CheckResult indicating the script execution result
+     */
     public @NotNull CheckResult runExpression(CompiledScript script, @NotNull Torrent torrent, @NotNull Peer peer, @NotNull Downloader downloader, @NotNull ExecutorService ruleExecuteExecutor) {

@Ghost-chu Ghost-chu merged commit 26ae4e0 into dev Nov 3, 2024
10 checks passed
@Ghost-chu Ghost-chu deleted the scriptengine-refactor branch November 3, 2024 14:48
This was referenced Nov 6, 2024
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