Skip to content

Conversation

@hykim02
Copy link
Collaborator

@hykim02 hykim02 commented May 9, 2025

Summary by CodeRabbit

  • New Features

    • Added real-time monitoring for HikariCP connection pool and Tomcat thread pool, providing periodic logs of their statuses.
  • Improvements

    • Enhanced logging in the diet request handling process to include thread name information for better traceability.
  • Chores

    • Integrated Micrometer and Prometheus dependencies to enable advanced application metrics collection.
    • Disabled caching on several cafeteria and campus-related methods to adjust data retrieval behavior.
    • Removed unused service methods and commented out inactive code for cleaner codebase maintenance.

@coderabbitai
Copy link

coderabbitai bot commented May 9, 2025

Walkthrough

This update introduces two new monitoring components for HikariCP and Tomcat thread pools, adds Micrometer dependencies to the build, and revises logging and service injection in the DietController. It also removes unused fields and methods, disables caching annotations on several service methods, and comments out a test method in UserService.

Changes

File(s) Change Summary
build.gradle Added Micrometer core and Prometheus registry dependencies.
src/main/java/com/example/Jinus/controller/DietController.java Changed injected service from dietServiceV2 to dietService; added SLF4J logger and thread name logging.
src/main/java/com/example/Jinus/monitor/HikariCPMonitor.java Added new HikariCPMonitor component with scheduled method to log HikariCP pool status every minute.
src/main/java/com/example/Jinus/monitor/TomcatThreadMonitor.java Added new TomcatThreadMonitor component with scheduled method to log Tomcat thread pool status every minute.
src/main/java/com/example/Jinus/service/diet/DietQueryService.java Removed unused dietRepositoryV2 field.
src/main/java/com/example/Jinus/service/userInfo/CollegeService.java Removed all methods except constructor and repository field; deleted logging statements.
src/main/java/com/example/Jinus/service/userInfo/UserService.java Fully commented out the selectCampusIdTest method, disabling it without deletion.
src/main/java/com/example/Jinus/service/cafeteria/CacheService.java Commented out @Cacheable annotation on getCafeteriaList method, disabling caching.
src/main/java/com/example/Jinus/service/cafeteria/CafeteriaQueryService.java Commented out @Cacheable annotations on getCafeteriaId and getImgUrl methods, disabling caching.
src/main/java/com/example/Jinus/service/cafeteria/CampusService.java Commented out @Cacheable annotations on getUserCampusName and getCampusId methods, disabling caching.

Sequence Diagram(s)

sequenceDiagram
    participant Scheduler
    participant HikariCPMonitor
    participant HikariDataSource
    participant HikariPoolMXBean

    Scheduler->>HikariCPMonitor: Trigger logHikariStatus() (every 60s)
    HikariCPMonitor->>HikariDataSource: getHikariPoolMXBean()
    HikariCPMonitor->>HikariPoolMXBean: Retrieve pool stats
    HikariCPMonitor->>Scheduler: Log pool stats to console
Loading
sequenceDiagram
    participant Scheduler
    participant TomcatThreadMonitor
    participant ServletWebServerApplicationContext
    participant TomcatWebServer
    participant Connector
    participant ProtocolHandler
    participant ThreadPoolExecutor

    Scheduler->>TomcatThreadMonitor: Trigger logTomcatThreadPoolStatus() (every 60s)
    TomcatThreadMonitor->>ServletWebServerApplicationContext: getWebServer()
    TomcatThreadMonitor->>TomcatWebServer: getTomcat().getConnector()
    TomcatThreadMonitor->>Connector: getProtocolHandler()
    TomcatThreadMonitor->>ProtocolHandler: getExecutor()
    TomcatThreadMonitor->>ThreadPoolExecutor: Retrieve thread pool stats
    TomcatThreadMonitor->>Scheduler: Log thread pool stats to console
Loading

Possibly related PRs

  • GNU-connect/Server-JavaSpring#39: Refactored DietController to use DietService instead of DietServiceV2, closely matching the service injection and controller changes in this PR.
  • GNU-connect/Server-JavaSpring#34: Disabled caching annotations in cafeteria-related service classes, related to this PR which disables caching in similar cafeteria service methods.

Poem

In the garden of code where the monitors bloom,
Hikari and Tomcat now sing a new tune.
With Micrometer seeds and logging anew,
Old caches are paused, and services pruned too.
A thread’s gentle whisper, a pool’s quiet cheer—
Springtime for servers is finally here!
🐇✨

Tip

⚡️ Faster reviews with caching
  • CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure Review - Disable Cache at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the Data Retention setting under your Organization Settings.

Enjoy the performance boost—your workflow just got faster.

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ 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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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 generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this 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.

Copy link

@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: 4

🧹 Nitpick comments (4)
src/main/java/com/example/Jinus/monitor/HikariCPMonitor.java (1)

19-19: Fix comment to match actual execution interval

The comment states "10초마다 상태 출력" (output every 10 seconds), but the fixedRate is set to 1000ms (1 second). Either adjust the comment or the execution interval to ensure they match.

-    @Scheduled(fixedRate = 1000) // 10초마다 상태 출력
+    @Scheduled(fixedRate = 1000) // 1초마다 상태 출력
src/main/java/com/example/Jinus/monitor/TomcatThreadMonitor.java (3)

23-23: Fix comment to match actual execution interval

The comment states "10초마다 출력" (output every 10 seconds), but the fixedRate is set to 1000ms (1 second). Either adjust the comment or the execution interval to ensure they match.

-    @Scheduled(fixedRate = 1000) // 10초마다 출력
+    @Scheduled(fixedRate = 1000) // 1초마다 출력

23-23: Consider less frequent monitoring in production

Running this monitoring task every second might generate excessive logs and cause unnecessary overhead. Consider a less frequent interval (e.g., 30 seconds or 1 minute) or making the interval configurable.

-    @Scheduled(fixedRate = 1000) // 10초마다 출력
+    @Scheduled(fixedRate = 60000) // 1분마다 출력

24-45: Add logging when expected components aren't found

The method has several instanceof checks that could fail silently. Consider adding log messages when the expected components aren't available to aid in troubleshooting.

     public void logTomcatThreadPoolStatus() {
         if (context.getWebServer() instanceof TomcatWebServer tomcatWebServer) {
             Connector connector = tomcatWebServer.getTomcat().getConnector();
             ProtocolHandler handler = connector.getProtocolHandler();
 
             if (handler instanceof AbstractProtocol<?> protocol) {
                 Executor executor = protocol.getExecutor();
 
                 if (executor instanceof ThreadPoolExecutor threadPoolExecutor) {
                     // existing code...
+                } else {
+                    log.debug("Tomcat executor is not an instance of ThreadPoolExecutor");
                 }
+            } else {
+                log.debug("Tomcat protocol handler is not an instance of AbstractProtocol");
             }
+        } else {
+            log.debug("Web server is not an instance of TomcatWebServer");
         }
     }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d2619a3 and 4797300.

📒 Files selected for processing (7)
  • build.gradle (1 hunks)
  • src/main/java/com/example/Jinus/controller/DietController.java (1 hunks)
  • src/main/java/com/example/Jinus/monitor/HikariCPMonitor.java (1 hunks)
  • src/main/java/com/example/Jinus/monitor/TomcatThreadMonitor.java (1 hunks)
  • src/main/java/com/example/Jinus/service/diet/DietQueryService.java (0 hunks)
  • src/main/java/com/example/Jinus/service/userInfo/CollegeService.java (0 hunks)
  • src/main/java/com/example/Jinus/service/userInfo/UserService.java (1 hunks)
💤 Files with no reviewable changes (2)
  • src/main/java/com/example/Jinus/service/userInfo/CollegeService.java
  • src/main/java/com/example/Jinus/service/diet/DietQueryService.java
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/main/java/com/example/Jinus/monitor/HikariCPMonitor.java (1)
src/main/java/com/example/Jinus/monitor/TomcatThreadMonitor.java (1)
  • Component (14-47)
src/main/java/com/example/Jinus/monitor/TomcatThreadMonitor.java (1)
src/main/java/com/example/Jinus/monitor/HikariCPMonitor.java (1)
  • Component (9-35)
🔇 Additional comments (6)
build.gradle (1)

49-51: Good addition of Micrometer dependencies for monitoring

The addition of Micrometer Core and Prometheus registry dependencies complements the existing actuator dependency and provides the foundation for the new monitoring components being introduced. This will enable better observability of the application's connection pools and thread usage.

src/main/java/com/example/Jinus/service/userInfo/UserService.java (1)

41-48: Appropriate removal of test method

Commenting out the selectCampusIdTest method makes sense now that proper HikariCP monitoring is being implemented. This method was likely used for testing connection pool behavior manually, but the new monitoring components provide a more systematic approach.

src/main/java/com/example/Jinus/controller/DietController.java (4)

11-13: Appropriate logger imports added.

The imports for SLF4J logging are correctly added to support the new logging functionality.


18-19: Good refactoring of service dependency and logger implementation.

The change from presumably dietServiceV2 to dietService aligns with the broader service layer refactoring mentioned in the PR summary. The static final logger is properly initialized following SLF4J best practices.


23-25: Thread monitoring enhancement looks good.

Adding thread name logging is valuable for monitoring and troubleshooting, especially in a multi-threaded environment like Spring. This change aligns well with the PR objective of adding monitoring capabilities.


26-26: Service method call updated to match refactored service.

The method call has been appropriately updated to use the refactored service.

Comment on lines +21 to +23
if (dataSource != null) {
HikariPoolMXBean poolMXBean = dataSource.getHikariPoolMXBean();

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add null check for poolMXBean

While there's a null check for the dataSource, there's no check for poolMXBean before accessing its methods, which could lead to a NullPointerException.

         if (dataSource != null) {
             HikariPoolMXBean poolMXBean = dataSource.getHikariPoolMXBean();
+            
+            if (poolMXBean == null) {
+                log.warn("HikariPoolMXBean is null, cannot monitor connection pool");
+                return;
+            }

Copy link

@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: 0

🧹 Nitpick comments (1)
src/main/java/com/example/Jinus/service/cafeteria/CacheService.java (1)

11-11: Consider removing unused import.

Since the @Cacheable annotation is now commented out and no longer used in this class, the import statement could be removed to keep the code clean.

-import org.springframework.cache.annotation.Cacheable;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4797300 and 95b7613.

📒 Files selected for processing (4)
  • src/main/java/com/example/Jinus/service/cafeteria/CacheService.java (1 hunks)
  • src/main/java/com/example/Jinus/service/cafeteria/CafeteriaQueryService.java (1 hunks)
  • src/main/java/com/example/Jinus/service/cafeteria/CampusService.java (2 hunks)
  • src/main/java/com/example/Jinus/service/userInfo/CollegeService.java (0 hunks)
💤 Files with no reviewable changes (1)
  • src/main/java/com/example/Jinus/service/userInfo/CollegeService.java
✅ Files skipped from review due to trivial changes (2)
  • src/main/java/com/example/Jinus/service/cafeteria/CampusService.java
  • src/main/java/com/example/Jinus/service/cafeteria/CafeteriaQueryService.java
🔇 Additional comments (2)
src/main/java/com/example/Jinus/service/cafeteria/CacheService.java (2)

58-64:

Details

❓ Verification inconclusive

Verify if this change aligns with PR objectives.

This change disables caching for cafeteria listings while the PR title indicates adding monitoring for Hikari and Tomcat. Consider documenting the rationale behind disabling the cache - is it related to performance monitoring, or is it addressing another issue?


🏁 Script executed:

#!/bin/bash
# Look for related monitoring code that might explain this change
echo "Searching for Hikari/Tomcat monitoring components:"
rg -i "hikari|tomcat" --type java src/main/java

Length of output: 2217


Confirm cache removal rationale

I noticed the @Cacheable annotation on getCafeteriaList(int campusId) was commented out, effectively disabling caching, while this PR focuses on adding Hikari and Tomcat monitoring. Please document why the cache was turned off here—e.g., is it to simplify performance metrics, avoid stale data during monitoring, or address another issue?

• File: src/main/java/com/example/Jinus/service/cafeteria/CacheService.java
Method: public List<CafeteriaDto> getCafeteriaList(int campusId)

If disabling the cache is intentional for the monitoring work, consider adding a brief comment or updating the PR description to capture this decision.


58-61:

Details

❓ Verification inconclusive

Caching disabled for getCafeteriaList method.

The Spring caching mechanism has been disabled for the getCafeteriaList method by commenting out the @Cacheable annotation. This means each call will now directly hit the database instead of checking the cache first.


🏁 Script executed:

#!/bin/bash
# Check if this is part of a consistent pattern across the codebase
# Looking for other commented out @Cacheable annotations in related files

echo "Checking for other disabled caching annotations in related services:"
rg -A 1 "//\s*@Cacheable" --type java src/main/java/com/example/Jinus/service/

Length of output: 1233


Disabled caching across cafeteria-related services

File: src/main/java/com/example/Jinus/service/cafeteria/CacheService.java (Lines 58–61)

//    @Cacheable(
//            value = "cafeteriaList",
//            key = "#p0",
//            cacheManager = "contentCacheManager")

The @Cacheable annotation has been commented out for the getCafeteriaList method, and similar annotations are disabled in:

  • src/main/java/com/example/Jinus/service/cafeteria/CampusService.java (campusId, campusName)
  • src/main/java/com/example/Jinus/service/cafeteria/CafeteriaQueryService.java (cafeteriaId, cafeteriaUrl)

With caching turned off, each call bypasses the cache and hits the database directly. Please confirm this change is intentional and that any performance impacts have been evaluated. If caching is still required, re-enable these annotations or revise your caching strategy.

Copy link

@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

🧹 Nitpick comments (3)
src/main/java/com/example/Jinus/monitor/TomcatThreadMonitor.java (3)

25-46: Consider adding error logging for edge cases

While the code correctly checks for instanceof conditions, it silently does nothing if the web server is not a TomcatWebServer or if the executor is not a ThreadPoolExecutor. Consider adding debug-level logging for these cases to help with troubleshooting.

@Scheduled(fixedRateString = "${monitor.pool.status.rate.ms:60000}") // 상태 출력 주기 (기본 1분)
public void logTomcatThreadPoolStatus() {
    if (context.getWebServer() instanceof TomcatWebServer tomcatWebServer) {
        Connector connector = tomcatWebServer.getTomcat().getConnector();
        ProtocolHandler handler = connector.getProtocolHandler();

        if (handler instanceof AbstractProtocol<?> protocol) {
            Executor executor = protocol.getExecutor();

            if (executor instanceof ThreadPoolExecutor threadPoolExecutor) {
                int max = threadPoolExecutor.getMaximumPoolSize();
                int poolSize = threadPoolExecutor.getPoolSize();
                int active = threadPoolExecutor.getActiveCount();
                long taskCount = threadPoolExecutor.getTaskCount();
                long completedTaskCount = threadPoolExecutor.getCompletedTaskCount();

                log.info("[Tomcat 스레드] MaxPoolSize: {}, PoolSize: {}, 활성: {}, TaskCount: {}, 완료: {}",
                        max, poolSize, active, taskCount, completedTaskCount);
+           } else {
+               log.debug("Tomcat executor is not a ThreadPoolExecutor");
            }
+       } else {
+           log.debug("Protocol handler is not an AbstractProtocol");
        }
+   } else {
+       log.debug("Web server is not a TomcatWebServer");
    }
}

1-47: Add JavaDoc comments for better documentation

Consider adding JavaDoc comments to describe the purpose of the class and the monitoring method. This will help other developers understand what the class does without having to read through the implementation details.

+/**
+ * Monitors Tomcat thread pool metrics and logs them at a configurable interval.
+ * This monitor works with the embedded Tomcat server in Spring Boot applications.
+ */
@Component
@Slf4j
public class TomcatThreadMonitor {

    private final ServletWebServerApplicationContext context;

    public TomcatThreadMonitor(ServletWebServerApplicationContext context) {
        this.context = context;
    }

+   /**
+    * Logs Tomcat thread pool statistics at a fixed rate.
+    * Retrieves and logs maximum pool size, current pool size, active thread count,
+    * total task count, and completed task count.
+    */
    @Scheduled(fixedRateString = "${monitor.pool.status.rate.ms:60000}") // 상태 출력 주기 (기본 1분)
    public void logTomcatThreadPoolStatus() {
        // Existing code...
    }
}

1-47: Consider adding Micrometer metrics for monitoring systems

While logging metrics is useful, consider also exposing these metrics via Micrometer so they can be collected by monitoring systems like Prometheus. This would allow for better visualization, alerting, and long-term trend analysis.

// Add these imports
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Gauge;
import jakarta.annotation.PostConstruct;

// In the class, add a MeterRegistry field and register gauges
private final MeterRegistry meterRegistry;

public TomcatThreadMonitor(ServletWebServerApplicationContext context, MeterRegistry meterRegistry) {
    this.context = context;
    this.meterRegistry = meterRegistry;
}

@PostConstruct
public void registerMetrics() {
    Gauge.builder("tomcat.threads.max", this, monitor -> monitor.getMaxThreads())
        .description("Maximum thread pool size")
        .register(meterRegistry);
    
    // Add similar gauges for other metrics
}

private int getMaxThreads() {
    // Similar logic to extract the max threads value
    // Return -1 if not available
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 95b7613 and eef3202.

📒 Files selected for processing (2)
  • src/main/java/com/example/Jinus/monitor/HikariCPMonitor.java (1 hunks)
  • src/main/java/com/example/Jinus/monitor/TomcatThreadMonitor.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/example/Jinus/monitor/HikariCPMonitor.java
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/main/java/com/example/Jinus/monitor/TomcatThreadMonitor.java (2)
src/test/java/com/example/Jinus/service/userInfo/UserServiceHikariCPTest.java (1)
  • Slf4j (17-74)
src/main/java/com/example/Jinus/monitor/HikariCPMonitor.java (1)
  • Component (10-35)
🔇 Additional comments (3)
src/main/java/com/example/Jinus/monitor/TomcatThreadMonitor.java (3)

1-24: Good class structure with proper dependency injection

The class is well-structured with appropriate component annotation and constructor-based dependency injection. This is a good practice compared to field injection.


25-26: Appropriate use of configurable scheduling

Using fixedRateString with a property placeholder allows for external configuration of the monitoring interval. The default value of 60,000ms (1 minute) is a reasonable choice for production monitoring.


27-40: Good use of pattern matching for instanceof (Java 16+ feature)

The code makes effective use of Java's pattern matching for instanceof (line 27 and 31), which makes the code more concise and readable compared to traditional casting.

Comment on lines +41 to +43
log.info("[Tomcat 스레드] MaxPoolSize: {}, PoolSize: {}, 활성: {}, TaskCount: {}, 완료: {}",
+ max, poolSize, active, taskCount, completedTaskCount);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove the unexpected '+' character in the logging statement

There's an unexpected '+' character at the beginning of line 42 that will cause a compilation error.

log.info("[Tomcat 스레드] MaxPoolSize: {}, PoolSize: {}, 활성: {}, TaskCount: {}, 완료: {}",
-        + max, poolSize, active, taskCount, completedTaskCount);
+        max, poolSize, active, taskCount, completedTaskCount);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
log.info("[Tomcat 스레드] MaxPoolSize: {}, PoolSize: {}, 활성: {}, TaskCount: {}, 완료: {}",
+ max, poolSize, active, taskCount, completedTaskCount);
}
log.info("[Tomcat 스레드] MaxPoolSize: {}, PoolSize: {}, 활성: {}, TaskCount: {}, 완료: {}",
max, poolSize, active, taskCount, completedTaskCount);

@hykim02 hykim02 closed this May 9, 2025
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.

1 participant