Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions k6/test-platform-thread.js → k6/case1-100vus.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ import http from 'k6/http';
import { check } from 'k6';

export const options = {
vus: 200,
vus: 100,
duration: '30s',
};

export default function () {
const res = http.post('http://host.docker.internal:8081/test/platform-thread');
const res = http.post(
`http://host.docker.internal:8081/test/notifications/trigger?userId=${__VU}`,
null,
{ timeout: '10s' }
);
check(res, { 'status 200': (r) => r.status === 200 });
}
8 changes: 6 additions & 2 deletions k6/test-virtual-thread.js → k6/case2-300vus.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ import http from 'k6/http';
import { check } from 'k6';

export const options = {
vus: 200,
vus: 300,
duration: '30s',
};

export default function () {
const res = http.post('http://host.docker.internal:8081/test/virtual-thread');
const res = http.post(
`http://host.docker.internal:8081/test/notifications/trigger?userId=${__VU}`,
null,
{ timeout: '10s' }
);
check(res, { 'status 200': (r) => r.status === 200 });
}
20 changes: 20 additions & 0 deletions k6/case3-spike.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import http from 'k6/http';
import { check } from 'k6';

export const options = {
stages: [
{ duration: '10s', target: 50 }, // 워밍업
{ duration: '5s', target: 500 }, // 스파이크 (Tomcat 200 2.5배)
{ duration: '20s', target: 500 }, // 스파이크 유지
{ duration: '5s', target: 0 }, // 종료
]
};

export default function () {
const res = http.post(
`http://host.docker.internal:8081/test/notifications/trigger?userId=${__VU}`,
null,
{ timeout: '10s' }
);
check(res, { 'status 200': (r) => r.status === 200 });
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

@EnableAsync
@EnableScheduling
@SpringBootApplication
public class AuctionNotificationApplication {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.example.auctionnotification.notification.controller;

import com.example.auctionnotification.notification.dto.NotificationMessage;
import com.example.auctionnotification.notification.enums.NotificationType;
import com.example.auctionnotification.notification.service.NotificationService;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Profile;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@Profile("!prod")
@RestController
@RequiredArgsConstructor
@RequestMapping("/test/notifications")
public class NotificationTestController {

private final NotificationService notificationService;

@PostMapping("/trigger")
public ResponseEntity<Void> trigger(@RequestParam(defaultValue = "1") Long userId) {
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 10, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

userId 유효성 검증을 고려하세요.

테스트 엔드포인트이지만 음수나 비정상적인 큰 값이 전달될 경우 예상치 못한 동작이 발생할 수 있습니다. 간단한 유효성 검증을 추가하는 것을 권장합니다.

✅ 유효성 검증 추가 제안
 `@PostMapping`("/trigger")
 public ResponseEntity<Void> trigger(`@RequestParam`(defaultValue = "1") Long userId) {
+    if (userId == null || userId <= 0) {
+        return ResponseEntity.badRequest().build();
+    }
     NotificationMessage message = new NotificationMessage(
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/com/example/auctionnotification/notification/controller/NotificationTestController.java`
at line 23, The trigger endpoint's userId parameter in
NotificationTestController.trigger lacks validation and may accept negative or
out-of-range values; add input validation at the start of the trigger method to
reject invalid userId (e.g., null, <=0, or > a sensible max) by returning a 400
Bad Request (ResponseEntity.badRequest()) or throwing a validation exception,
and document the constraint; use the method name
NotificationTestController.trigger and parameter userId to locate where to add
the check and ensure unit tests cover invalid, boundary, and valid cases.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

이것도 테스트용이라 넘어갈게

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@soomin0209 이해합니다! 테스트 전용 엔드포인트이고 @Profile("!prod")로 프로덕션에서는 비활성화되어 있으니 괜찮습니다. 👍

NotificationMessage message = new NotificationMessage(
NotificationType.NEW_BID,
userId,
1L,
"테스트 경매 상품"
);
notificationService.save(message);
return ResponseEntity.ok().build();
}
Comment on lines +22 to +32
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 10, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

예외 처리를 추가하세요.

notificationService.save()에서 예외가 발생하면 500 에러가 반환되어 k6 부하 테스트 결과가 왜곡될 수 있습니다. 테스트 엔드포인트라도 일관된 응답을 보장하기 위해 예외 처리가 필요합니다.

🛡️ 예외 처리 추가 제안
 `@PostMapping`("/trigger")
 public ResponseEntity<Void> trigger(`@RequestParam`(defaultValue = "1") Long userId) {
+    try {
         NotificationMessage message = new NotificationMessage(
                 NotificationType.NEW_BID,
                 userId,
                 1L,
                 "테스트 경매 상품"
         );
         notificationService.save(message);
         return ResponseEntity.ok().build();
+    } catch (Exception e) {
+        // 로그 기록 후 테스트를 위해 일관된 응답 반환
+        return ResponseEntity.status(500).build();
+    }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/com/example/auctionnotification/notification/controller/NotificationTestController.java`
around lines 22 - 32, Wrap the call to notificationService.save(...) inside
NotificationTestController.trigger with a try-catch that catches Exception, logs
the error (including the exception) and prevents a 500 response, then return a
consistent ResponseEntity (e.g., ResponseEntity.ok().build()) even on failure;
specifically, surround the notificationService.save(message) call, catch
Exception e, call your controller logger/error reporter with the exception and a
short context message, and still return a successful ResponseEntity from trigger
so k6 tests receive a consistent response.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

테스트용이라서 그냥 넘어갈게 테스트 결과 왜곡 없이 나오는거 확인했어

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@soomin0209 확인해 주셨군요! 실제 테스트 결과에 영향이 없다면 괜찮습니다. 진행하세요 👍

}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public SseEmitter subscribe(Long userId) {
return emitter;
}

@Async("notificationExecutorWithVT")
@Async
Comment thread
coderabbitai[bot] marked this conversation as resolved.
public void send(Long userId, NotificationResponse response) {
SseEmitter emitter = emitters.get(userId);
if (emitter == null) return;
Expand All @@ -57,7 +57,7 @@ public void send(Long userId, NotificationResponse response) {
}
}

@Async("notificationExecutorWithVT")
@Async
@Scheduled(fixedRate = 30000)
public void sendPing() {
for (Map.Entry<Long, SseEmitter> entry : emitters.entrySet()) {
Expand Down

This file was deleted.