Skip to content

Commit

Permalink
Merge pull request #194 from Genti2024/staging
Browse files Browse the repository at this point in the history
Feat: #185 #187
  • Loading branch information
LeeJae-H authored Nov 2, 2024
2 parents 7dd4d60 + c6e752b commit d1ef47d
Show file tree
Hide file tree
Showing 16 changed files with 187 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,17 @@ public class PGREQSaveRequestDto {
@Schema(description = "프롬프트", example = "벚꽃길에서 벤치에 앉아있는 사진이요")
String prompt;

@Schema(description = "포즈 사진")
CommonPictureKeyUpdateRequestDto posePicture;

@NotNull
@Size(max = 3, min = 1, message = "사용자의 얼굴 사진 개수는 최소 1개, 최대 3개입니다.")
@Schema(description = "얼굴 사진 리스트")
List<@NotNull CommonPictureKeyUpdateRequestDto> facePictureList;

@NotNull
@Schema(description = "카메라 앵글")
CameraAngle cameraAngle;
@NotNull
@Schema(description = "프레임")

ShotCoverage shotCoverage;

@NotNull
@Schema(description = "사진 비율")
PictureRatio pictureRatio;
Expand All @@ -59,7 +56,7 @@ public PGREQSaveRequestDto(String prompt, CommonPictureKeyUpdateRequestDto poseP
public PGREQSaveCommand toCommand() {
return PGREQSaveCommand.builder()
.prompt(this.prompt)
.posePictureKey(this.posePicture.getKey())
.posePictureKey(this.posePicture != null ? this.posePicture.getKey() : null)
.cameraAngle(this.cameraAngle)
.shotCoverage(this.shotCoverage)
.pictureRatio(this.pictureRatio)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,31 +187,13 @@ public PictureGenerateRequest createPGREQ(Long userId, PGREQSaveCommand pgreqSav
throwIfNewPictureGenerateRequestNotAvailable(foundUser);

String lockKey = "LOCK:" + userId + ":" + "createPGREQ";
Boolean lockGranted = redisTemplate.opsForValue().setIfAbsent(lockKey, "locked", LOCK_TTL_SECONDS, TimeUnit.SECONDS);
if (Boolean.FALSE.equals(lockGranted)) {
if (!acquireLock(lockKey)) {
throw ExpectedException.withLogging(ResponseCode.PictureGenerateRequestAlreadyProcessed);
}
try {
String posePictureKey = "";
PicturePose foundPicturePose = null;
if (!Objects.isNull(pgreqSaveCommand.getPosePictureKey())) {
posePictureKey = pgreqSaveCommand.getPosePictureKey();
String finalPosePictureKey = posePictureKey;
foundPicturePose = pictureService.findByKeyPicturePose(posePictureKey).orElseGet(() -> {
log.info("""
%s 유저가 요청에 포함한 포즈참고사진 key [%s] 기존 사진을 찾을 수 없어 신규 저장""".formatted(foundUser.getEmail(),
finalPosePictureKey));
return pictureService.updatePicture(
CreatePicturePoseCommand.builder().key(finalPosePictureKey).uploader(foundUser).build());
});
}

List<String> facePictureUrl = pgreqSaveCommand.getFacePictureKeyList();
List<PictureUserFace> uploadedFacePictureList = pictureService.updateIfNotExistsPictureUserFace(
facePictureUrl, foundUser);

String promptAdvanced = openAIService.getAdvancedPrompt(
new PromptAdvancementRequestCommand(pgreqSaveCommand.getPrompt()));
PicturePose picturePose = processPicturePose(pgreqSaveCommand, foundUser);
List<PictureUserFace> uploadedFacePictureList = pictureService.updateIfNotExistsPictureUserFace(pgreqSaveCommand.getFacePictureKeyList(), foundUser);
String promptAdvanced = openAIService.getAdvancedPrompt(new PromptAdvancementRequestCommand(pgreqSaveCommand.getPrompt()));
log.info(promptAdvanced);

PictureGenerateRequest createdPGREQ = PictureGenerateRequest.builder()
Expand All @@ -221,7 +203,7 @@ public PictureGenerateRequest createPGREQ(Long userId, PGREQSaveCommand pgreqSav
.shotCoverage(pgreqSaveCommand.getShotCoverage())
.cameraAngle(pgreqSaveCommand.getCameraAngle())
.pictureRatio(pgreqSaveCommand.getPictureRatio())
.picturePose(foundPicturePose)
.picturePose(picturePose)
.userFacePictureList(uploadedFacePictureList)
.build();

Expand All @@ -230,10 +212,32 @@ public PictureGenerateRequest createPGREQ(Long userId, PGREQSaveCommand pgreqSav

return savedPGREQ;
} finally {
Boolean keyDeleted = redisTemplate.delete(lockKey);
if (Boolean.FALSE.equals(keyDeleted)) {
log.error("Redis에 key {} 값이 존재하지 않습니다.", lockKey);
}
releaseLock(lockKey);
}
}

private PicturePose processPicturePose(PGREQSaveCommand pgreqSaveCommand, User foundUser) {
String posePictureKey = pgreqSaveCommand.getPosePictureKey();
if (Objects.isNull(posePictureKey)) {
return null;
}
return pictureService.findByKeyPicturePose(posePictureKey).orElseGet(() -> {
log.info("""
%s 유저가 요청에 포함한 포즈참고사진 key [%s] 기존 사진을 찾을 수 없어 신규 저장""".formatted(foundUser.getEmail(),
posePictureKey));
return pictureService.updatePicture(
CreatePicturePoseCommand.builder().key(posePictureKey).uploader(foundUser).build());
});
}

private Boolean acquireLock(String lockKey) {
return redisTemplate.opsForValue().setIfAbsent(lockKey, "locked", LOCK_TTL_SECONDS, TimeUnit.SECONDS);
}

private void releaseLock(String lockKey) {
Boolean keyDeleted = redisTemplate.delete(lockKey);
if (Boolean.FALSE.equals(keyDeleted)) {
log.error("Redis에 key {} 값이 존재하지 않습니다.", lockKey);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.gt.genti.picturegenerateresponse.api;

import com.gt.genti.error.ResponseCode;
import com.gt.genti.picture.PictureRatio;
import com.gt.genti.response.GentiResponse;
import com.gt.genti.swagger.AuthorizedUser;
import com.gt.genti.swagger.EnumResponse;
import com.gt.genti.swagger.EnumResponses;
import com.gt.genti.user.model.AuthUser;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotNull;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestParam;

@AuthorizedUser
@Tag(name = "[FrontendPGRESController] 프론트엔드 개발자가 직접 사진 생성 응답 처리하기", description = "개발 서버 한정입니다.")
public interface FrontendPGRESApi {

@Operation(summary = "사진 생성 응답 처리", description = "사진 생성 응답을 처리합니다.")
@EnumResponses(value = {
@EnumResponse(ResponseCode.OK)
})
ResponseEntity<GentiResponse.ApiResult<Boolean>> finishPGRESByFrontend(
@AuthUser Long userId);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.gt.genti.picturegenerateresponse.controller;

import com.gt.genti.picture.PictureRatio;
import com.gt.genti.picturegenerateresponse.service.PictureGenerateWorkService;
import com.gt.genti.response.GentiResponse;
import com.gt.genti.user.model.AuthUser;
import jakarta.validation.constraints.NotNull;
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({"staging", "local"})
@RestController
@RequestMapping("/api/v1/frontend/picture-generate-responses")
@RequiredArgsConstructor
public class FrontendPGRESController {

private final PictureGenerateWorkService pictureGenerateWorkService;

@PostMapping
ResponseEntity<GentiResponse.ApiResult<Boolean>> finishPGRESByFrontend(
@AuthUser Long userId
){
return GentiResponse.success(pictureGenerateWorkService.finishPGRESByFrontend(userId));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import java.util.Objects;
import java.util.Optional;

import com.gt.genti.picture.PictureRatio;
import com.gt.genti.picture.completed.repository.PictureCompletedRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand Down Expand Up @@ -51,6 +53,7 @@ public class PictureGenerateWorkService {
private final CreatorRepository creatorRepository;
private final PictureGenerateResponseRepository pictureGenerateResponseRepository;
private final PictureGenerateRequestRepository pictureGenerateRequestRepository;
private final PictureCompletedRepository pictureCompletedRepository;
private final SettlementRepository settlementRepository;
private final DepositRepository depositRepository;
private final RequestMatchService requestMatchService;
Expand Down Expand Up @@ -298,6 +301,36 @@ public void expire(PictureGenerateResponse pictureGenerateResponse) {

}

public Boolean finishPGRESByFrontend(Long userId){
User foundUser = findUserById(userId);
Optional<PictureGenerateRequest> pgreq = pictureGenerateRequestRepository.findTop1ByRequesterOrderByIdDesc(foundUser);
if (pgreq.isPresent()){
PictureGenerateRequest foundpgreq = pgreq.get();
if(foundpgreq.getPictureGenerateRequestStatus().equals(PictureGenerateRequestStatus.MATCH_TO_ADMIN)){
Optional<PictureGenerateResponse> pgres = pictureGenerateResponseRepository.findByRequest(pgreq.get());
if(pgres.isPresent()) {
PictureGenerateResponse foundpgres = pgres.get();
String key = switch (foundpgreq.getPictureRatio()) {
case PictureRatio.RATIO_GARO -> "DEV/ADMIN_UPLOADED_IMAGE/3.png";
case PictureRatio.RATIO_SERO -> "DEV/ADMIN_UPLOADED_IMAGE/1.png";
default -> "";
};
PictureCompleted pictureCompleted = PictureCompleted.builder()
.key(key)
.pictureGenerateResponse(foundpgres)
.uploadedBy(foundUser)
.requester(foundUser)
.pictureRatio(foundpgreq.getPictureRatio())
.build();
pictureCompletedRepository.save(pictureCompleted);
foundpgres.adminSubmit();
return true;
}
}
}
return false;
}

private User findUserById(Long userId) {
return userRepository.findById(userId)
.orElseThrow(() -> ExpectedException.withLogging(ResponseCode.UserNotFound, userId));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.List;

import com.gt.genti.responseexample.dto.response.ExampleWithSquarePicture;
import org.springframework.http.ResponseEntity;

import com.gt.genti.error.ResponseCode;
Expand All @@ -24,4 +25,11 @@ public interface UserResponseExampleApi {
@EnumResponse(ResponseCode.OK)
})
ResponseEntity<ApiResult<List<ExampleWithPictureFindResponseDto>>> getAllResponseExamples();

@Operation(summary = "사진 생성 뷰에서의 예시 사진 조회", description = "예시 사진&프롬프트를 조회합니다." + "<br/>"
+ "정방형 비율의 사진입니다.")
@EnumResponses(value = {
@EnumResponse(ResponseCode.OK)
})
ResponseEntity<ApiResult<List<ExampleWithSquarePicture>>> getAllResponseExamplesInGenerateView();
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import java.util.List;

import com.gt.genti.responseexample.dto.response.ExampleWithSquarePicture;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
Expand Down Expand Up @@ -31,4 +32,11 @@ public ResponseEntity<ApiResult<List<ExampleWithPictureFindResponseDto>>> getAll
return success(responseExampleService.getAllResponseExamples());
}


@Logging(item = LogItem.RESPONSE_EXAMPLE, action = LogAction.VIEW, requester = LogRequester.USER)
@GetMapping("/with-picture-square")
public ResponseEntity<ApiResult<List<ExampleWithSquarePicture>>> getAllResponseExamplesInGenerateView(){
return success(responseExampleService.getAllResponseExamplesInGenerateView());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.gt.genti.responseexample.dto.response;

import com.gt.genti.aws.AwsUtils;
import com.gt.genti.picture.responseexample.model.ResponseExample;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Schema(name = "[ResponseExample][Admin&User] 사진 생성뷰1에서의 예시 사진 응답 dto")
@Getter
@NoArgsConstructor
public class ExampleWithSquarePicture {
@Schema(description = "해당 사진의 Url", example = "https://**")
String url;

@Schema(description = "에시 프롬프트", example = "벚꽃길에서 벤치에 앉아있어요")
String prompt;

public ExampleWithSquarePicture(ResponseExample responseExample) {
this.url = AwsUtils.CLOUDFRONT_BASEURL + "/" + responseExample.getKey();
this.prompt = responseExample.getExamplePrompt();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.Optional;
import java.util.stream.Collectors;

import com.gt.genti.responseexample.dto.response.ExampleWithSquarePicture;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
Expand Down Expand Up @@ -67,4 +68,13 @@ public void addResponseExamples(List<ExampleSaveCommand> commandList,
.build()).toList());
}

public List<ExampleWithSquarePicture> getAllResponseExamplesInGenerateView() {
List<ExampleWithSquarePicture> examples = responseExampleRepository.findAllByPromptOnlyIsTrue()
.stream()
.map(ExampleWithSquarePicture::new)
.collect(Collectors.toList());
Collections.shuffle(examples);

return examples.subList(0, 5);
}
}
2 changes: 1 addition & 1 deletion genti-api/src/main/resources/file-appender.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf8</charset>
</encoder>
</appender>
</appender>
3 changes: 2 additions & 1 deletion genti-domain/src/main/java/com/gt/genti/common/EnumUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ private static <E extends Enum<E> & ConvertableEnum> E toEnum(Class<E> enumType,
if (value == null) {
E enumNullValue = enumType.getEnumConstants()[0].getNullValue();
if (enumNullValue == null) {
throw ExpectedException.withLogging(ResponseCode.NotNullableEnum, enumType);
// throw ExpectedException.withLogging(ResponseCode.NotNullableEnum, enumType);
return null;
} else {
return enumNullValue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ public String convertToDatabaseColumn(T attribute) {
} catch (NullPointerException e) {
T enumNullValue = enumClassType.getEnumConstants()[0].getNullValue();
if (enumNullValue == null) {
throw ExpectedException.withLogging(ResponseCode.NotNullableEnum, enumClassType.getName());
// throw ExpectedException.withLogging(ResponseCode.NotNullableEnum, enumClassType.getName());
return null;
} else {
return enumNullValue.getStringValue();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@
public interface ResponseExampleRepository extends JpaRepository<ResponseExample, Long> {
List<ResponseExample> findAllByPromptOnlyIsFalse();
Page<ResponseExample> findAllByPromptOnlyIsFalse(Pageable pageable);
List<ResponseExample> findAllByPromptOnlyIsTrue();
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,11 @@ public class PictureGenerateRequest extends BaseTimeEntity {
@JoinColumn(name = "picture_pose_id")
PicturePose picturePose;

@Column(name = "camera_angle", nullable = false)
@Column(name = "camera_angle")
@Convert(converter = CameraAngleConverter.class)
CameraAngle cameraAngle;

@Column(name = "shot_coverage", nullable = false)
@Column(name = "shot_coverage")
@Convert(converter = ShotCoverageConverter.class)
ShotCoverage shotCoverage;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public interface PictureGenerateRequestRepository

List<PictureGenerateRequest> findAllByRequester(User requester);

Optional<PictureGenerateRequest> findTop1ByRequesterOrderByIdDesc(User requester);

Page<PictureGenerateRequest> findAllByRequester(User requester, Pageable pageable);

@Query("select pgr from PictureGenerateRequest pgr "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

import com.gt.genti.picturegeneraterequest.model.PictureGenerateRequest;
import org.springframework.data.jpa.repository.JpaRepository;

import com.gt.genti.picturegenerateresponse.model.PictureGenerateResponse;
import com.gt.genti.picturegenerateresponse.model.PictureGenerateResponseStatus;

public interface PictureGenerateResponseRepository extends JpaRepository<PictureGenerateResponse, Long> {
List<PictureGenerateResponse> findAllByCreatedAtBeforeAndStatusIs(LocalDateTime expireThreshold, PictureGenerateResponseStatus status);
Optional<PictureGenerateResponse> findByRequest(PictureGenerateRequest pictureGenerateRequest);
}

0 comments on commit d1ef47d

Please sign in to comment.