Skip to content

Commit c282306

Browse files
authored
[Feature] 퀘스트 생성 시 AI서버에 라벨링 요청을 한다 (#100)
feature: 퀘스트 생성 시 AI서버에 라벨링 요청을 한다
1 parent 2dc4b07 commit c282306

File tree

10 files changed

+127
-3
lines changed

10 files changed

+127
-3
lines changed

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ dependencies {
2929
implementation 'org.springframework.boot:spring-boot-starter-validation:3.1.2'
3030
implementation 'org.springframework.boot:spring-boot-starter-web:3.1.2'
3131
implementation 'org.springframework.boot:spring-boot-starter-actuator:3.1.2'
32+
implementation 'org.springframework.boot:spring-boot-starter-webflux:3.1.2'
3233

3334
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0'
3435
asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor'
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package daybyquest.global.config;
22

3+
import daybyquest.global.infra.AiServerProperties;
34
import daybyquest.image.domain.BaseImageProperties;
45
import org.springframework.boot.context.properties.EnableConfigurationProperties;
56
import org.springframework.context.annotation.Configuration;
67

78
@Configuration
8-
@EnableConfigurationProperties(BaseImageProperties.class)
9+
@EnableConfigurationProperties({BaseImageProperties.class, AiServerProperties.class})
910
public class PropertiesConfig {
1011

1112
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package daybyquest.global.config;
2+
3+
import daybyquest.global.infra.AiServerProperties;
4+
import org.springframework.context.annotation.Bean;
5+
import org.springframework.context.annotation.Configuration;
6+
import org.springframework.http.HttpHeaders;
7+
import org.springframework.http.MediaType;
8+
import org.springframework.web.reactive.function.client.WebClient;
9+
10+
@Configuration
11+
public class WebClientConfig {
12+
13+
@Bean
14+
public WebClient webClient(final AiServerProperties properties) {
15+
return WebClient.builder()
16+
.baseUrl(properties.getDomain())
17+
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
18+
.build();
19+
}
20+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package daybyquest.global.infra;
2+
3+
4+
import lombok.Getter;
5+
import org.springframework.boot.context.properties.ConfigurationProperties;
6+
import org.springframework.boot.context.properties.bind.ConstructorBinding;
7+
8+
@Getter
9+
@ConfigurationProperties(prefix = "ai")
10+
public class AiServerProperties {
11+
12+
private final String domain;
13+
14+
@ConstructorBinding
15+
public AiServerProperties(final String domain) {
16+
this.domain = domain;
17+
}
18+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package daybyquest.quest.application;
2+
3+
import java.util.List;
4+
5+
public interface QuestClient {
6+
7+
void requestLabels(final Long questId, final List<String> identifiers);
8+
}

src/main/java/daybyquest/quest/application/SaveQuestService.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,23 @@ public class SaveQuestService {
2727

2828
private final ImageIdentifierGenerator generator;
2929

30+
private final QuestClient questClient;
31+
3032
public SaveQuestService(final Quests quests, final Badges badges, final Images images,
31-
final ImageIdentifierGenerator generator) {
33+
final ImageIdentifierGenerator generator, final QuestClient questClient) {
3234
this.quests = quests;
3335
this.badges = badges;
3436
this.images = images;
3537
this.generator = generator;
38+
this.questClient = questClient;
3639
}
3740

3841
@Transactional
3942
public Long invoke(final SaveQuestRequest request, final List<MultipartFile> files) {
4043
final Quest quest = toEntity(request, toImageList(files));
41-
return quests.save(quest);
44+
final Long questId = quests.save(quest);
45+
questClient.requestLabels(questId, quest.getImages().stream().map(Image::getIdentifier).toList());
46+
return questId;
4247
}
4348

4449
private List<Image> toImageList(final List<MultipartFile> files) {
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package daybyquest.quest.dto.request;
2+
3+
import java.util.List;
4+
5+
public record LabelQuestRequest(List<String> imageIdentifiers) {
6+
7+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package daybyquest.quest.infra;
2+
3+
import daybyquest.quest.application.QuestClient;
4+
import java.util.List;
5+
import org.springframework.context.annotation.Profile;
6+
import org.springframework.stereotype.Component;
7+
import org.springframework.web.reactive.function.client.WebClient;
8+
9+
@Component
10+
@Profile("!prod")
11+
public class QuestStubClient implements QuestClient {
12+
13+
private final WebClient webClient;
14+
15+
public QuestStubClient(final WebClient webClient) {
16+
this.webClient = webClient;
17+
}
18+
19+
@Override
20+
public void requestLabels(final Long questId, final List<String> identifiers) {
21+
return;
22+
}
23+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package daybyquest.quest.infra;
2+
3+
import daybyquest.global.error.exception.BadRequestException;
4+
import daybyquest.quest.application.QuestClient;
5+
import daybyquest.quest.dto.request.LabelQuestRequest;
6+
import java.util.List;
7+
import org.springframework.context.annotation.Profile;
8+
import org.springframework.http.HttpStatusCode;
9+
import org.springframework.stereotype.Component;
10+
import org.springframework.web.reactive.function.client.WebClient;
11+
12+
@Component
13+
@Profile("prod")
14+
public class QuestWebClient implements QuestClient {
15+
16+
private final WebClient webClient;
17+
18+
public QuestWebClient(final WebClient webClient) {
19+
this.webClient = webClient;
20+
}
21+
22+
@Override
23+
public void requestLabels(final Long questId, final List<String> identifiers) {
24+
final LabelQuestRequest request = new LabelQuestRequest(identifiers);
25+
webClient.post()
26+
.uri(uriBuilder -> uriBuilder.pathSegment("quest", questId.toString(), "shot").build())
27+
.bodyValue(request)
28+
.retrieve()
29+
.onStatus(HttpStatusCode::is4xxClientError, response -> {
30+
throw new BadRequestException();
31+
})
32+
.onStatus(HttpStatusCode::is5xxServerError, response -> {
33+
throw new BadRequestException();
34+
})
35+
.toBodilessEntity()
36+
.block();
37+
}
38+
}

src/main/resources/application-web.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ image:
1212
tracker:
1313
days: 60
1414

15+
ai:
16+
domain: http://localhost:8080
17+
1518
spring:
1619
servlet:
1720
multipart:

0 commit comments

Comments
 (0)