Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/be/dev' into be/feat/242
Browse files Browse the repository at this point in the history
  • Loading branch information
tackyu committed Aug 14, 2024
2 parents e6fefdc + 01082b1 commit caf8eb3
Show file tree
Hide file tree
Showing 14 changed files with 201 additions and 381 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import net.pengcook.recipe.dto.RecipeOfUserRequest;
import net.pengcook.recipe.dto.RecipeRequest;
import net.pengcook.recipe.dto.RecipeResponse;
import net.pengcook.recipe.dto.RecipeStepRequest;
import net.pengcook.recipe.dto.RecipeStepResponse;
import net.pengcook.recipe.service.RecipeService;
import net.pengcook.recipe.service.RecipeStepService;
Expand Down Expand Up @@ -62,18 +61,4 @@ public List<MainRecipeResponse> readRecipesOfUser(
public List<RecipeStepResponse> readRecipeSteps(@PathVariable long recipeId) {
return recipeStepService.readRecipeSteps(recipeId);
}

@GetMapping("/{recipeId}/steps/{sequence}")
public RecipeStepResponse readRecipeStep(@PathVariable long recipeId, @PathVariable long sequence) {
return recipeStepService.readRecipeStep(recipeId, sequence);
}

@PostMapping("/{recipeId}/steps")
@ResponseStatus(HttpStatus.CREATED)
public RecipeStepResponse createRecipeStep(
@PathVariable long recipeId,
@RequestBody @Valid RecipeStepRequest recipeStepRequest
) {
return recipeStepService.createRecipeStep(recipeId, recipeStepRequest);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
package net.pengcook.recipe.dto;

import jakarta.annotation.Nullable;
import jakarta.validation.constraints.Min;

public record PageRecipeRequest(@Min(0) int pageNumber, @Min(1) int pageSize) {
public record PageRecipeRequest(
@Min(0) int pageNumber,
@Min(1) int pageSize,
@Nullable String category,
@Nullable String keyword,
@Nullable Long userId
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public record RecipeRequest(
@Min(0) @Max(10) int difficulty,
@NotBlank String description,
@NotEmpty List<String> categories,
@NotEmpty List<IngredientCreateRequest> ingredients
@NotEmpty List<IngredientCreateRequest> ingredients,
List<RecipeStepRequest> recipeSteps
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ public record RecipeStepResponse(
String image,
String description,
int sequence,
LocalTime cookingTime) {
LocalTime cookingTime
) {

public RecipeStepResponse(RecipeStep recipeStep) {
this(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
package net.pengcook.recipe.repository;

import jakarta.annotation.Nullable;
import java.util.List;
import net.pengcook.recipe.domain.Recipe;
import net.pengcook.recipe.dto.RecipeDataResponse;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface RecipeRepository extends JpaRepository<Recipe, Long> {

@Query("""
SELECT r.id
SELECT DISTINCT r.id
FROM Recipe r
LEFT JOIN CategoryRecipe cr ON cr.recipe = r
LEFT JOIN Category c ON cr.category = c
WHERE (:category IS NULL OR c.name = :category)
AND (:keyword IS NULL OR CONCAT(r.title, r.description) LIKE CONCAT('%', :keyword, '%'))
AND (:userId IS NULL OR r.author.id = :userId)
ORDER BY r.id DESC
""")
List<Long> findRecipeIds(Pageable pageable);
List<Long> findRecipeIdsByCategoryAndKeyword(
Pageable pageable,
@Param("category") @Nullable String category,
@Param("keyword") @Nullable String keyword,
@Param("userId") @Nullable Long userId
);

@Query("""
SELECT new net.pengcook.recipe.dto.RecipeDataResponse(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,16 @@ public class RecipeService {
private final CategoryService categoryService;
private final IngredientService ingredientService;
private final S3ClientService s3ClientService;
private final RecipeStepService recipeStepService;

public List<MainRecipeResponse> readRecipes(PageRecipeRequest pageRecipeRequest) {
Pageable pageable = getValidatedPageable(pageRecipeRequest.pageNumber(), pageRecipeRequest.pageSize());
List<Long> recipeIds = recipeRepository.findRecipeIds(pageable);
List<Long> recipeIds = recipeRepository.findRecipeIdsByCategoryAndKeyword(
pageable,
pageRecipeRequest.category(),
pageRecipeRequest.keyword(),
pageRecipeRequest.userId()
);

List<RecipeDataResponse> recipeDataResponses = recipeRepository.findRecipeData(recipeIds);
return convertToMainRecipeResponses(recipeDataResponses);
Expand All @@ -67,6 +73,7 @@ public RecipeResponse createRecipe(UserInfo userInfo, RecipeRequest recipeReques
Recipe savedRecipe = recipeRepository.save(recipe);
categoryService.saveCategories(savedRecipe, recipeRequest.categories());
ingredientService.register(recipeRequest.ingredients(), savedRecipe);
recipeStepService.saveRecipeSteps(savedRecipe.getId(), recipeRequest.recipeSteps());

return new RecipeResponse(savedRecipe);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,30 +31,25 @@ public List<RecipeStepResponse> readRecipeSteps(long recipeId) {
return convertToRecipeStepResponses(recipeSteps);
}

public RecipeStepResponse readRecipeStep(long recipeId, long sequence) {
RecipeStep recipeStep = recipeStepRepository.findByRecipeIdAndSequence(recipeId, sequence)
.orElseThrow(() -> new NotFoundException("ν•΄λ‹Ήλ˜λŠ” λ ˆμ‹œν”Ό μŠ€ν… 정보가 μ—†μŠ΅λ‹ˆλ‹€."));

return new RecipeStepResponse(recipeStep);
public void saveRecipeSteps(Long savedRecipeId, List<RecipeStepRequest> recipeStepRequests) {
Recipe savedRecipe = recipeRepository.findById(savedRecipeId)
.orElseThrow(() -> new NotFoundException("ν•΄λ‹Ήλ˜λŠ” λ ˆμ‹œν”Όκ°€ μ—†μŠ΅λ‹ˆλ‹€."));
recipeStepRequests.forEach(recipeStepRequest -> saveRecipeStep(savedRecipe, recipeStepRequest));
}

public RecipeStepResponse createRecipeStep(long recipeId, RecipeStepRequest recipeStepRequest) {
validateRecipeStepSequence(recipeId, recipeStepRequest.sequence());
Recipe recipe = getRecipeByRecipeId(recipeId);
private void saveRecipeStep(Recipe savedRecipe, RecipeStepRequest recipeStepRequest) {
String imageUrl = getValidatedImageUrl(recipeStepRequest.image());
String description = recipeStepRequest.description();
LocalTime cookingTime = getValidatedCookingTime(recipeStepRequest.cookingTime());

Optional<RecipeStep> existingRecipeStep = recipeStepRepository.findByRecipeIdAndSequence(
recipeId,
recipeStepRequest.sequence()
RecipeStep recipeStep = new RecipeStep(
savedRecipe,
imageUrl,
recipeStepRequest.description(),
recipeStepRequest.sequence(),
cookingTime
);

RecipeStep recipeStep = existingRecipeStep
.map(currentRecipeStep -> currentRecipeStep.update(imageUrl, description, cookingTime))
.orElseGet(() -> saveRecipeStep(recipe, imageUrl, recipeStepRequest, cookingTime));

return new RecipeStepResponse(recipeStep);
recipeStepRepository.save(recipeStep);
}

private List<RecipeStepResponse> convertToRecipeStepResponses(List<RecipeStep> recipeSteps) {
Expand All @@ -63,19 +58,6 @@ private List<RecipeStepResponse> convertToRecipeStepResponses(List<RecipeStep> r
.toList();
}

private void validateRecipeStepSequence(long recipeId, int sequence) {
int previousSequence = sequence - 1;
if (previousSequence >= 1) {
recipeStepRepository.findByRecipeIdAndSequence(recipeId, previousSequence)
.orElseThrow(() -> new InvalidParameterException("이전 μŠ€ν…μ΄ λ“±λ‘λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€."));
}
}

private Recipe getRecipeByRecipeId(long recipeId) {
return recipeRepository.findById(recipeId)
.orElseThrow(() -> new NotFoundException("ν•΄λ‹Ήλ˜λŠ” λ ˆμ‹œν”Όκ°€ μ—†μŠ΅λ‹ˆλ‹€."));
}

private String getValidatedImageUrl(String image) {
if (image == null) {
return null;
Expand All @@ -95,21 +77,4 @@ private LocalTime getValidatedCookingTime(String cookingTime) {
throw new InvalidParameterException("μ μ ˆν•˜μ§€ μ•Šμ€ μ‘°λ¦¬μ‹œκ°„μž…λ‹ˆλ‹€.");
}
}

private RecipeStep saveRecipeStep(
Recipe recipe,
String imageUrl,
RecipeStepRequest recipeStepRequest,
LocalTime cookingTime
) {
RecipeStep recipeStep = new RecipeStep(
recipe,
imageUrl,
recipeStepRequest.description(),
recipeStepRequest.sequence(),
cookingTime
);

return recipeStepRepository.save(recipeStep);
}
}
37 changes: 26 additions & 11 deletions backend/src/main/resources/docker-compose-dev.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
volumes:
db:
grafana:
prometheus:
prom:

services:
db:
Expand Down Expand Up @@ -37,11 +37,23 @@ services:
restart: unless-stopped
command: -config.file=/etc/loki/local-config.yaml

prometheus:
node:
image: prom/node-exporter
restart: unless-stopped
pid: host
command:
- '--path.rootfs=/host'
volumes:
- '/:/host:ro,rslave'

prom:
image: prom/prometheus
restart: unless-stopped
volumes:
- prometheus:/prometheus
- prom:/prometheus
links:
- app
- node
entrypoint:
- sh
- -euc
Expand All @@ -53,10 +65,13 @@ services:
scrape_interval: 15s
static_configs:
- targets: ['app:8080']
- job_name: 'node'
scrape_interval: 15s
static_configs:
- targets: ['node:9100']
EOF
/bin/prometheus
links:
- app
grafana:
image: grafana/grafana
Expand All @@ -65,6 +80,11 @@ services:
- grafana:/var/lib/grafana
environment:
- GF_SERVER_ROOT_URL=https://dev.mon.pengcook.net
ports:
- 3000:3000
links:
- loki
- prom
entrypoint:
- sh
- -euc
Expand All @@ -87,14 +107,9 @@ services:
type: prometheus
access: proxy
orgId: 1
url: http://prometheus:9090
url: http://prom:9090
basicAuth: false
isDefault: false
editable: false
EOF
/run.sh
ports:
- 3000:3000
links:
- loki
- prometheus
35 changes: 27 additions & 8 deletions backend/src/main/resources/docker-compose-local.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
volumes:
db:
grafana:
prometheus:
prom:

services:
db:
Expand All @@ -27,13 +27,26 @@ services:
- 3100:3100
command: -config.file=/etc/loki/local-config.yaml

prometheus:
node:
image: prom/node-exporter
restart: unless-stopped
pid: host
ports:
- 9100:9100
command:
- '--path.rootfs=/host'
volumes:
- '/:/host:ro'

prom:
image: prom/prometheus
restart: unless-stopped
volumes:
- prometheus:/prometheus
- prom:/prometheus
ports:
- 9090:9090
links:
- node
entrypoint:
- sh
- -euc
Expand All @@ -45,6 +58,11 @@ services:
scrape_interval: 15s
static_configs:
- targets: ['host.docker.internal:8080']
- job_name: 'node'
scrape_interval: 15s
static_configs:
- targets: ['node_exporter:9100']
EOF
/bin/prometheus
Expand All @@ -56,6 +74,11 @@ services:
environment:
- GF_AUTH_ANONYMOUS_ENABLED=true
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
ports:
- 3000:3000
links:
- loki
- prom
entrypoint:
- sh
- -euc
Expand All @@ -78,13 +101,9 @@ services:
type: prometheus
access: proxy
orgId: 1
url: http://prometheus:9090
url: http://prom:9090
basicAuth: false
isDefault: false
editable: false
EOF
/run.sh
ports:
- 3000:3000
links:
- loki
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class CategoryRecipeRepositoryTest {

@Test
@DisplayName("μš”μ²­ν•œ μΉ΄ν…Œκ³ λ¦¬μ™€ νŽ˜μ΄μ§€μ— ν•΄λ‹Ήν•˜λŠ” λ ˆμ‹œν”Ό id λͺ©λ‘μ„ λ°˜ν™˜ν•œλ‹€.")
void findRecipeIds() {
void findRecipeIdsByCategoryAndKeyword() {
Pageable pageable = PageRequest.of(0, 3);

List<Long> recipeIds = repository.findRecipeIdsByCategoryName("ν•œμ‹", pageable);
Expand Down
Loading

0 comments on commit caf8eb3

Please sign in to comment.