12
12
import com .example .busan .reservation .dto .CreateReservationRequest ;
13
13
import com .example .busan .reservation .dto .ReservationResponse ;
14
14
import com .example .busan .reservation .dto .UpdateReservationRequest ;
15
+ import com .example .busan .reservation .service .ReservationNamedLockFacade ;
16
+ import com .example .busan .reservation .service .ReservationService ;
15
17
import com .example .busan .room .domain .Room ;
16
18
import com .example .busan .room .domain .RoomRepository ;
17
19
import com .example .busan .room .dto .CreateRoomRequest ;
23
25
import org .springframework .boot .test .mock .mockito .MockBean ;
24
26
import org .springframework .data .domain .Pageable ;
25
27
28
+ import java .time .LocalDateTime ;
26
29
import java .util .List ;
27
30
import java .util .Objects ;
28
31
import java .util .Optional ;
32
+ import java .util .concurrent .CountDownLatch ;
33
+ import java .util .concurrent .ExecutorService ;
34
+ import java .util .concurrent .Executors ;
29
35
30
36
import static java .time .LocalDateTime .now ;
31
37
import static java .time .LocalDateTime .of ;
@@ -40,6 +46,8 @@ class ReservationServiceTest {
40
46
@ Autowired
41
47
private ReservationService reservationService ;
42
48
@ Autowired
49
+ private ReservationNamedLockFacade reservationFacade ;
50
+ @ Autowired
43
51
private ReservationRepository reservationRepository ;
44
52
@ Autowired
45
53
private MemberRepository memberRepository ;
@@ -71,6 +79,63 @@ void create() {
71
79
assertThat (reservationRepository .findAll ()).hasSize (1 );
72
80
}
73
81
82
+ @ Test
83
+ @ DisplayName ("동시적으로 중복 예약을 하면 1개만 생성된다" )
84
+ void create_concurrency () throws InterruptedException {
85
+ //given
86
+ final int userCount = 100 ;
87
+ final ExecutorService executorService = Executors .newFixedThreadPool (32 );
88
+ final CountDownLatch countDownLatch = new CountDownLatch (userCount );
89
+
90
+ //when
91
+ for (int i = 0 ; i < userCount ; i ++) {
92
+ executorService .submit (() -> {
93
+ try {
94
+ reservationFacade .create (
95
+ new CreateReservationRequest (
96
+ 1L ,
97
+ LocalDateTime .of (2050 , 11 , 10 , 13 , 0 ),
98
+ LocalDateTime .of (2050 , 11 , 10 , 15 , 30 )));
99
+ } finally {
100
+ countDownLatch .countDown ();
101
+ }
102
+ });
103
+ }
104
+ countDownLatch .await ();
105
+
106
+ //then
107
+ assertThat (reservationRepository .count ()).isOne ();
108
+ }
109
+
110
+ @ Test
111
+ @ DisplayName ("동시적으로 100개의 요청 성공" )
112
+ void create_concurrency2 () throws InterruptedException {
113
+ //given
114
+ final int userCount = 100 ;
115
+ final ExecutorService executorService = Executors .newFixedThreadPool (32 );
116
+ final CountDownLatch countDownLatch = new CountDownLatch (userCount );
117
+
118
+ //when
119
+ for (int i = 0 ; i < userCount ; i ++) {
120
+ final long roomId = i ;
121
+ executorService .submit (() -> {
122
+ try {
123
+ reservationFacade .create (
124
+ new CreateReservationRequest (
125
+ roomId ,
126
+ LocalDateTime .of (2050 , 11 , 10 , 13 , 0 ),
127
+ LocalDateTime .of (2050 , 11 , 10 , 15 , 30 )));
128
+ } finally {
129
+ countDownLatch .countDown ();
130
+ }
131
+ });
132
+ }
133
+ countDownLatch .await ();
134
+
135
+ //then
136
+ assertThat (reservationRepository .count ()).isEqualTo (userCount );
137
+ }
138
+
74
139
@ Test
75
140
@ DisplayName ("다른 예약과 시간이 겹치면 생성할 수 없다" )
76
141
void create_fail () {
0 commit comments