Skip to content

Development: Check bean instantiations on startup - #11065

Merged
krusche merged 63 commits into
developfrom
chore/test-instantiations-on-startup
Aug 13, 2025
Merged

Development: Check bean instantiations on startup#11065
krusche merged 63 commits into
developfrom
chore/test-instantiations-on-startup

Conversation

@tobias-lippert

@tobias-lippert tobias-lippert commented Jun 28, 2025

Copy link
Copy Markdown
Contributor

Checklist

General

Server

Motivation and Context

In the last couple of weeks we merged different PRs targeting the startup performance of the Artemis server application.
If we do not check these values for every PR performance regressions might be introduced without noticing it.

Description

Added a github action that checks the number of instantiated beans on startup and the longest chain length of bean instantiations. Additionally, we check the longest chain length after the deferred eager initialization

Steps for Testing

Testserver States

You can manage test servers using Helios. Check environment statuses in the environment list. To deploy to a test server, go to the CI/CD page, find your PR or branch, and trigger the deployment.

Review Progress

Code Review

  • Code Review 1
  • Code Review 2

Summary by CodeRabbit

  • New Features

    • Enhanced tracking and reporting of long dependency/instantiation chains during startup and deferred initialization, with thresholded alerts, chain logs and GraphViz exports for development.
    • Emitted completion event after deferred eager initialization to trigger post-init reporting.
  • Bug Fixes

    • Improved detection of empty/absent database state during migration to avoid false errors.
  • Chores

    • Ignored deferred initialization violation dot file from version control.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 28, 2025
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 28, 2025
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 28, 2025
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 28, 2025
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 28, 2025
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 28, 2025
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 28, 2025
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 28, 2025
coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 6, 2025
@github-actions

github-actions Bot commented Aug 6, 2025

Copy link
Copy Markdown

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report204 ran200 passed3 skipped1 failed1h 5m 38s 331ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/exercise/programming/ProgrammingExerciseStaticCodeAnalysis.spec.ts
ts.Static code analysis tests › Configures SCA grading and makes a successful submission with SCA errors❌ failure2m 13s 373ms

coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 10, 2025
@github-actions

Copy link
Copy Markdown

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report204 ran200 passed3 skipped1 failed1h 2m 15s 161ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/exercise/programming/ProgrammingExerciseStaticCodeAnalysis.spec.ts
ts.Static code analysis tests › Configures SCA grading and makes a successful submission with SCA errors❌ failure2m 10s 502ms

coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 12, 2025
@github-actions

Copy link
Copy Markdown

End-to-End (E2E) Test Results Summary

TestsPassed ✅Skipped ⚠️FailedTime ⏱
End-to-End (E2E) Test Report205 ran202 passed3 skipped0 failed1h 3m 31s 813ms
TestResultTime ⏱
No test annotations available

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (6)
src/main/java/de/tum/cit/aet/artemis/core/config/BeanInstantiationTracer.java (6)

34-37: Avoid magic numbers; externalize thresholds to prevent drift with GitHub Action

The comment notes manual sync with the workflow. Prefer sourcing thresholds from system properties or config to avoid drift.

Apply this minimal change to read from a system property with sane defaults:

-    private static final int STARTUP_MAX_DEPENDENCY_CHAIN_THRESHOLD = 9;
+    private static final int STARTUP_MAX_DEPENDENCY_CHAIN_THRESHOLD =
+            Integer.getInteger("artemis.startup.maxBeanChain", 9);

-    private static final int DEFERRED_INIT_MAX_DEPENDENCY_CHAIN_THRESHOLD = 16;
+    private static final int DEFERRED_INIT_MAX_DEPENDENCY_CHAIN_THRESHOLD =
+            Integer.getInteger("artemis.deferred.maxBeanChain", 16);

You can then set these via the GitHub Action Java args to ensure a single source of truth. Would you like a follow-up patch to wire these from the workflow?


65-77: Race between max depth and longestChain updates; ensure atomicity of the pair

maxCallStackSize and longestChain can get out of sync under concurrency. A thread may fail the CAS yet still update longestChain, or two threads can interleave causing the chain not to match the recorded max.

Make the update linearizable by coupling the successful CAS with the chain update:

-            int prevMax = maxCallStackSize.get();
-            if (depth > prevMax && maxCallStackSize.compareAndSet(prevMax, depth)) {
-                longestChain.set(new ArrayList<>(stack));
-            }
+            int prev;
+            boolean updated = false;
+            do {
+                prev = maxCallStackSize.get();
+                if (depth <= prev) {
+                    break;
+                }
+                updated = maxCallStackSize.compareAndSet(prev, depth);
+            }
+            while (!updated);
+            if (updated) {
+                longestChain.set(new ArrayList<>(stack));
+            }

94-97: Nit: spelling and punctuation in Javadoc

Minor doc polish.

-     * Prints the bean instantiation graph to a DOT file that can be visualized on <a href="http://www.webgraphviz.com/">GraphViz</a> when the application starts up.
+     * Prints the bean instantiation graph to a DOT file that can be visualized on <a href="http://www.webgraphviz.com/">Graphviz</a> when the application starts up.
-     * This is useful for debugging and performance improvements, but should not be enabled in production environments
+     * This is useful for debugging and performance improvements, but should not be enabled in production environments.

106-106: Emit summary metric at INFO to facilitate GitHub Action parsing

If the Action parses logs, relying on DEBUG may hide the metric depending on log level config in CI.

-            log.debug("Bean instantiation graph exported to startupBeans.dot ({} edges, longest dependency chain length: {})", edges.size(), longestChain.get().size());
+            log.info("Bean instantiation graph exported to startupBeans.dot ({} edges, longest dependency chain length: {})", edges.size(), longestChain.get().size());

If CI already enables DEBUG for this class, feel free to skip. Otherwise, consider promoting just the summary lines to INFO.


151-151: Nit: remove trailing space in log message placeholder

Cosmetic cleanup.

-            log.error("Failed to write {} ", filename, e);
+            log.error("Failed to write {}", filename, e);

154-154: Consider promoting deferred max summary to INFO as well

Same rationale as Line 106 for CI parsing.

-        log.debug("Maximum dependency chain length during deferred eager init: {}", maxCallStackSize.get());
+        log.info("Maximum dependency chain length during deferred eager init: {}", maxCallStackSize.get());
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4d100d6 and e01e1cf.

⛔ Files ignored due to path filters (1)
  • .github/workflows/bean-instantiations.yml is excluded by !**/*.yml
📒 Files selected for processing (1)
  • src/main/java/de/tum/cit/aet/artemis/core/config/BeanInstantiationTracer.java (7 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/main/java/**/*.java

⚙️ CodeRabbit Configuration File

naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

Files:

  • src/main/java/de/tum/cit/aet/artemis/core/config/BeanInstantiationTracer.java
🧠 Learnings (2)
📚 Learning: 2025-08-04T11:27:40.470Z
Learnt from: tobias-lippert
PR: ls1intum/Artemis#11252
File: src/main/java/de/tum/cit/aet/artemis/core/service/telemetry/TelemetryService.java:45-45
Timestamp: 2025-08-04T11:27:40.470Z
Learning: In the Artemis application, there's a custom DeferredEagerBeanInitializer component that forces initialization of all lazy singleton beans after the FullStartupEvent is published. This allows beans to be marked Lazy for performance during startup while ensuring they're still initialized before serving requests. The PostConstruct methods on lazy beans will execute when the DeferredEagerBeanInitializer calls context.getBean(name) on them.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/core/config/BeanInstantiationTracer.java
📚 Learning: 2025-06-15T14:14:33.083Z
Learnt from: tobias-lippert
PR: ls1intum/Artemis#10951
File: src/main/java/de/tum/cit/aet/artemis/lti/config/DistributedStateAuthorizationRequestRepository.java:26-26
Timestamp: 2025-06-15T14:14:33.083Z
Learning: In the Artemis application, FullStartupEvent is published as the last event in the startup sequence, and lazy beans that need to respond to this event are guaranteed to be instantiated before or during its publication, so EventListener(FullStartupEvent.class) methods on Lazy beans will execute properly.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/core/config/BeanInstantiationTracer.java
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: Build and Push Docker Image / Build Docker Image for ls1intum/artemis
  • GitHub Check: Build and Push Docker Image / Build Docker Image for ls1intum/artemis
  • GitHub Check: Build .war artifact
  • GitHub Check: client-tests
  • GitHub Check: client-style
  • GitHub Check: server-tests
  • GitHub Check: server-style
  • GitHub Check: bean-instantiation-check
  • GitHub Check: Analyse
🔇 Additional comments (1)
src/main/java/de/tum/cit/aet/artemis/core/config/BeanInstantiationTracer.java (1)

130-149: Deferred chains export: good coverage and DOT generation

The new listener cleanly exports only offending deferred chains and logs them with lengths. Resource handling and iteration are correct.

@github-actions

Copy link
Copy Markdown

End-to-End (E2E) Test Results Summary

TestsPassed ✅SkippedFailedTime ⏱
End-to-End (E2E) Test Report1 ran1 passed0 skipped0 failed1s 626ms
TestResultTime ⏱
No test annotations available

@github-actions

Copy link
Copy Markdown

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report205 ran201 passed3 skipped1 failed1h 2m 53s 766ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/exercise/programming/ProgrammingExerciseStaticCodeAnalysis.spec.ts
ts.Static code analysis tests › Configures SCA grading and makes a successful submission with SCA errors❌ failure2m 17s 680ms

@tobias-lippert tobias-lippert added this to the 8.4.0 milestone Aug 12, 2025

@ahmetsenturk ahmetsenturk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

code lgtm and output makes sense 👍

@florian-glombik florian-glombik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code

@github-actions

Copy link
Copy Markdown

End-to-End (E2E) Test Results Summary

TestsPassed ✅Skipped ⚠️FailedTime ⏱
End-to-End (E2E) Test Report205 ran202 passed3 skipped0 failed56m 6s 492ms
TestResultTime ⏱
No test annotations available

@krusche
krusche merged commit 05e5103 into develop Aug 13, 2025
30 of 34 checks passed
@krusche
krusche deleted the chore/test-instantiations-on-startup branch August 13, 2025 13:43
@github-project-automation github-project-automation Bot moved this from Ready For Review to Merged in Artemis Development Aug 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core Pull requests that affect the corresponding module ready to merge server Pull requests that update Java code. (Added Automatically!)

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

5 participants