Skip to content

Commit 14413a1

Browse files
committed
Profile fetch 시 항상 db 조회를 하던 문제를 수정함
switchIfEmpty 는 값을 평가한 후 동작하므로, 항상 함수가 실행됨 + Mono 는 empty 시 error 를 발생시키지 않으므로 , onnext,onerror 도 타지않는 짜증나는 문제가 있었음. 이를 single() 메소드를 통해 NoSuchElementException을 발생시키도록 함
1 parent c86bf73 commit 14413a1

File tree

11 files changed

+110
-44
lines changed

11 files changed

+110
-44
lines changed

profile/src/main/java/com/example/research/profile/config/RedisConfig.java

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import org.springframework.context.annotation.Bean;
66
import org.springframework.context.annotation.Configuration;
7-
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
87
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
98
import org.springframework.data.redis.core.ReactiveRedisTemplate;
109
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
@@ -32,14 +31,8 @@ public LettuceConnectionFactory connectionFactoryForDev() {
3231
}
3332

3433
@Bean
35-
public ReactiveRedisTemplate<String, String> reactiveRedisTemplate(ReactiveRedisConnectionFactory connectionFactory) {
36-
log.info("call reactiveRedisTemplate");
37-
return new ReactiveRedisTemplate<>(connectionFactory, RedisSerializationContext.string());
38-
}
39-
40-
@Bean
41-
public ReactiveRedisTemplate<String, Profile> reactiveJsonPersonRedisTemplate(
42-
ReactiveRedisConnectionFactory connectionFactory) {
34+
public ReactiveRedisTemplate<String, Profile> reactiveJsonProfileRedisTemplate(
35+
LettuceConnectionFactory connectionFactory) {
4336
log.info("call reactiveJsonPersonRedisTemplate");
4437
RedisSerializationContext<String, Profile> serializationContext = RedisSerializationContext
4538
.<String, Profile>newSerializationContext(new StringRedisSerializer())

profile/src/main/java/com/example/research/profile/entity/cache/Profile.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,13 @@
99
import java.util.Set;
1010

1111
import lombok.AllArgsConstructor;
12+
import lombok.EqualsAndHashCode;
1213
import lombok.Getter;
1314
import lombok.NoArgsConstructor;
15+
import lombok.ToString;
1416

17+
@ToString
18+
@EqualsAndHashCode
1519
@Getter
1620
@NoArgsConstructor
1721
@AllArgsConstructor

profile/src/main/java/com/example/research/profile/entity/cache/ProfileRepository.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,11 @@ public Flux<Profile> findAll() {
2222
}
2323

2424
public Mono<Profile> findById(String id) {
25-
return template.<String, Profile>opsForHash().get("profiles", id);
25+
return template.<String, Profile>opsForHash().get("profiles", id).single();
2626
}
2727

2828
public Mono<Profile> save(Profile profile) {
2929
return template.<String, Profile>opsForHash().put("profiles", profile.getId(), profile)
30-
.log()
3130
.map(p -> profile);
3231

3332
}

profile/src/main/java/com/example/research/profile/entity/event/Event.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
import java.io.Serializable;
44

55
public interface Event extends Serializable {
6-
String getId();
6+
String getTag();
77
}

profile/src/main/java/com/example/research/profile/entity/event/ProfileChangedEvent.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.example.research.profile.entity.event;
22

3+
import com.example.research.profile.entity.storage.Profile;
4+
35
import java.time.LocalDateTime;
46

57
import lombok.Getter;
@@ -10,12 +12,21 @@
1012
public class ProfileChangedEvent implements ProfileEvent {
1113
@Getter public static final String ID = ProfileChangedEvent.class.getSimpleName();
1214

15+
@NonNull String id;
1316
@NonNull String name;
1417
@NonNull Integer age;
1518
@NonNull String sex; // man, woman
1619
@NonNull LocalDateTime createdAt;
1720

18-
@Override public String getId() {
21+
public static ProfileChangedEvent from(Profile storeProfile) {
22+
return new ProfileChangedEvent(
23+
storeProfile.getId(),
24+
storeProfile.getName(), storeProfile.getAge(),
25+
storeProfile.getSex(), storeProfile.getCreatedAt()
26+
);
27+
}
28+
29+
@Override public String getTag() {
1930
return ID;
2031
}
2132
}

profile/src/main/java/com/example/research/profile/entity/event/ProfileSavedEvent.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,23 @@
1313
@Getter
1414
@RequiredArgsConstructor
1515
public class ProfileSavedEvent implements ProfileEvent {
16-
public static final String ID = ProfileSavedEvent.class.getSimpleName();
16+
public static final String TAG = ProfileSavedEvent.class.getSimpleName();
1717

18+
@NonNull String id;
1819
@NonNull String name;
1920
@NonNull Integer age;
2021
@NonNull String sex; // man, woman
2122
@NonNull LocalDateTime createdAt;
2223

2324
public static ProfileSavedEvent from(Profile storeProfile) {
2425
return new ProfileSavedEvent(
26+
storeProfile.getId(),
2527
storeProfile.getName(), storeProfile.getAge(),
2628
storeProfile.getSex(), storeProfile.getCreatedAt()
2729
);
2830
}
2931

30-
@Override public String getId() {
31-
return ID;
32+
@Override public String getTag() {
33+
return TAG;
3234
}
3335
}

profile/src/main/java/com/example/research/profile/v1/profile/ProfileEventListener.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ public class ProfileEventListener {
1313

1414
@EventListener public void onProfileSavedEventReceived(ProfileSavedEvent event) {
1515
log.info("event received : {}" + event);
16+
1617
}
1718
}

profile/src/main/java/com/example/research/profile/v1/profile/ProfileHandler.java

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
import reactor.core.publisher.Flux;
2020
import reactor.core.publisher.Mono;
2121

22-
import static org.springframework.http.MediaType.APPLICATION_JSON;
22+
import static org.springframework.web.reactive.function.BodyInserters.fromObject;
23+
import static org.springframework.web.reactive.function.server.ServerResponse.ok;
2324

2425
@Slf4j
2526
@Component
@@ -31,28 +32,27 @@ public class ProfileHandler {
3132

3233
@NonNull
3334
public Mono<ServerResponse> fetchProfiles(ServerRequest request) {
34-
// send Event
35-
Flux<Profile> profiles = profileRepository.findAll()
36-
.switchIfEmpty(
37-
Flux.fromIterable(profileStorageRepository.findAll())
38-
.map(Profile::from) // TODO send Event
39-
);
40-
41-
return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(profiles, Profile.class);
35+
Flux<Profile> profiles = Flux.fromIterable(profileStorageRepository.findAll())
36+
.flatMap(profile -> {
37+
log.info("call switchIfEmpty");
38+
return profileRepository.save(Profile.from(profile));
39+
});
40+
return ok().contentType(MediaType.APPLICATION_JSON).body(profiles, Profile.class);
4241
}
4342

4443
@NonNull
4544
public Mono<ServerResponse> fetch(ServerRequest request) {
4645
String id = request.pathVariable("id");
4746
Mono<Profile> profile = profileRepository.findById(id)
48-
.switchIfEmpty(
49-
Mono.just(
50-
profileStorageRepository.findById(id)
51-
.orElseThrow(() -> new IllegalStateException("profile not found"))
52-
)
53-
.map(Profile::from) // TODO send Event
54-
);
55-
return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(profile, Profile.class);
47+
.onErrorResume(throwable -> {
48+
log.error("throwable : ", throwable);
49+
return Mono.just(
50+
profileStorageRepository.findById(id)
51+
.orElseThrow(() -> new IllegalStateException("profile not found"))
52+
)
53+
.flatMap(storedProfile -> profileRepository.save(Profile.from(storedProfile)));
54+
});
55+
return ok().contentType(MediaType.APPLICATION_JSON).body(profile, Profile.class);
5656
}
5757

5858
@NonNull

profile/src/main/java/com/example/research/profile/v1/profile/ProfileRouter.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
1111
import static org.springframework.web.reactive.function.server.RequestPredicates.POST;
12+
import static org.springframework.web.reactive.function.server.RequestPredicates.PUT;
1213
import static org.springframework.web.reactive.function.server.RequestPredicates.accept;
1314

1415
@Configuration
@@ -19,6 +20,8 @@ public class ProfileRouter {
1920
handler::fetchProfiles)
2021
.andRoute(POST("/api/v1/profiles").and(accept(MediaType.APPLICATION_JSON)),
2122
request -> handler.save(request.bodyToMono(ProfileSaveRequest.class)))
23+
.andRoute(PUT("/api/v1/profiles").and(accept(MediaType.APPLICATION_JSON)),
24+
handler::update)
2225
.andRoute(GET("/api/v1/profiles/{id}").and(accept(MediaType.APPLICATION_JSON)),
2326
handler::fetch);
2427
}

profile/src/test/java/com/example/research/profile/entity/cache/test/ProfileRepositoryTests.java

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,19 @@
2121

2222
import java.time.LocalDateTime;
2323
import java.util.ArrayList;
24+
import java.util.Collections;
2425
import java.util.List;
2526
import java.util.Optional;
26-
import java.util.stream.Collectors;
27+
import java.util.stream.StreamSupport;
2728

2829
import javax.persistence.EntityManager;
2930

3031
import reactor.test.StepVerifier;
3132

33+
import static org.hamcrest.core.Is.is;
3234
import static org.junit.Assert.assertEquals;
3335
import static org.junit.Assert.assertNotNull;
36+
import static org.junit.Assert.assertThat;
3437

3538
@RunWith(SpringRunner.class)
3639
@SpringBootTest(classes = TestApplicationContext.class)
@@ -52,6 +55,27 @@ public void setup() {
5255
connectionFactory.getConnection().flushDb();
5356
}
5457

58+
@Test public void 프로필_조회_레디스() {
59+
final Profile generateProfile = generateProfile();
60+
61+
// GIVEN
62+
StepVerifier.create(profileRepository.save(generateProfile))
63+
.expectNextCount(1)
64+
.verifyComplete();
65+
66+
StepVerifier.create(profileRepository.findById(generateProfile.getId()))
67+
.expectNext(generateProfile)
68+
.verifyComplete();
69+
70+
Iterable<Profile> profiles = profileRepository.findAll().toIterable();
71+
Profile profile = StreamSupport.stream(profiles.spliterator(), false)
72+
.filter(generateProfile::equals)
73+
.findAny()
74+
.orElseThrow(() -> new IllegalStateException("profile must not be null"));
75+
76+
assertThat(profile, is(generateProfile));
77+
}
78+
5579
@Test public void 프로필_조회() {
5680
final List<Tag> generatedTags = generateRandomTagData();
5781

@@ -69,7 +93,7 @@ public void setup() {
6993
});
7094

7195
// to redis
72-
StepVerifier.create(profileRepository.save(generateProfile(generatedTags)))
96+
StepVerifier.create(profileRepository.save(generateProfile()))
7397
.expectNextCount(1)
7498
.verifyComplete();
7599

@@ -78,10 +102,11 @@ public void setup() {
78102
.verifyComplete();
79103
}
80104

81-
private static Profile generateProfile(List<Tag> tags) {
105+
private static Profile generateProfile() {
82106
return new Profile(
83-
RandomData.alphabetic(20),
84-
tags.stream().map(Tag::getNo).collect(Collectors.toSet())
107+
RandomData.alphabetic(20), RandomData.name(),
108+
RandomData.randomInteger(10, 45), RandomData.randomBoolean() ? "man" : "woman",
109+
RandomData.randomBoolean(), Collections.emptySet()
85110
);
86111
}
87112

0 commit comments

Comments
 (0)