Skip to content

Commit

Permalink
Merge pull request #2 from lotteon2/O2F-1052/feat/read-auctions
Browse files Browse the repository at this point in the history
O2 f 1052/feat/read auctions
  • Loading branch information
ssjy4974 authored Jan 3, 2024
2 parents 5475927 + 1eb49b4 commit 4c5d46c
Show file tree
Hide file tree
Showing 8 changed files with 218 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@

import com.dailyon.auctionservice.dto.request.CreateAuctionRequest;
import com.dailyon.auctionservice.dto.response.CreateAuctionResponse;
import com.dailyon.auctionservice.dto.response.ReadAuctionPageResponse;
import com.dailyon.auctionservice.facade.AuctionFacade;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.validation.Valid;

Expand All @@ -22,4 +28,9 @@ public class AuctionAdminController {
public ResponseEntity<CreateAuctionResponse> createAuction(@Valid @RequestBody CreateAuctionRequest createAuctionRequest) {
return ResponseEntity.status(HttpStatus.CREATED).body(auctionFacade.createAuction(createAuctionRequest));
}

@GetMapping("/auction")
public Mono<ReadAuctionPageResponse> readAuctions(Pageable pageable) {
return Mono.just(auctionFacade.readAuctions(pageable));
}
}
12 changes: 11 additions & 1 deletion src/main/java/com/dailyon/auctionservice/document/Auction.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
@NoArgsConstructor
@AllArgsConstructor
@DynamoDBTable(tableName = "auctions")
public class Auction {
public class Auction implements Comparable<Auction> {
@Id
@DynamoDBHashKey
@DynamoDBAutoGeneratedKey
Expand Down Expand Up @@ -46,6 +46,11 @@ public class Auction {
@Builder.Default
private boolean isEnded = false;

@DynamoDBTypeConverted(converter = DynamoDbConfig.LocalDateTimeConverter.class)
@DynamoDBAttribute(attributeName = "created_at")
@Builder.Default
private LocalDateTime createdAt = LocalDateTime.now();

public static Auction create(
Long auctionProductId,
String auctionName,
Expand All @@ -61,4 +66,9 @@ public static Auction create(
.startAt(startAt)
.build();
}

@Override
public int compareTo(Auction o) {
return o.getCreatedAt().compareTo(this.getCreatedAt());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.dailyon.auctionservice.dto.response;

import com.dailyon.auctionservice.document.Auction;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.domain.Page;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ReadAuctionPageResponse {
private long totalElements;
private int totalPages;
private List<ReadAuctionResponse> responses;

public static ReadAuctionPageResponse of(Page<Auction> auctions) {
return ReadAuctionPageResponse.builder()
.totalPages(auctions.getTotalPages())
.totalElements(auctions.getTotalElements())
.responses(auctions.stream()
.map(ReadAuctionResponse::of)
.collect(Collectors.toList()))
.build();
}

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class ReadAuctionResponse {
private String id;
private Long auctionProductId;
private String auctionName;
private Integer startBidPrice;
private Integer maximumWinner;
private LocalDateTime startAt;
private boolean isStarted;
private boolean isEnded;

public static ReadAuctionResponse of(Auction auction) {
return ReadAuctionResponse.builder()
.id(auction.getId())
.auctionProductId(auction.getAuctionProductId())
.auctionName(auction.getAuctionName())
.startBidPrice(auction.getStartBidPrice())
.maximumWinner(auction.getMaximumWinner())
.startAt(auction.getStartAt())
.isStarted(auction.isStarted())
.isEnded(auction.isEnded())
.build();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
import com.dailyon.auctionservice.document.Auction;
import com.dailyon.auctionservice.dto.request.CreateAuctionRequest;
import com.dailyon.auctionservice.dto.response.CreateAuctionResponse;
import com.dailyon.auctionservice.dto.response.ReadAuctionPageResponse;
import com.dailyon.auctionservice.service.AuctionService;
import feign.FeignException;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.util.List;

Expand All @@ -31,4 +34,8 @@ public CreateAuctionResponse createAuction(CreateAuctionRequest createAuctionReq
}
return CreateAuctionResponse.create(auction, productResponse);
}

public ReadAuctionPageResponse readAuctions(Pageable pageable) {
return ReadAuctionPageResponse.of(auctionService.readAuctions(pageable));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import org.socialsignin.spring.data.dynamodb.repository.EnableScan;
import org.springframework.data.repository.CrudRepository;

/* Caused by: com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException: Auction[created_at]; no HASH key for GSI auction_sort_idx
https://stackoverflow.com/questions/68067091/sorting-not-supported-for-scan-expressions-and-no-hash-key-for-gsi-for-dynamodbp
*/
@EnableScan
public interface AuctionRepository extends CrudRepository<Auction, String> {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,16 @@
import com.dailyon.auctionservice.dto.request.CreateAuctionRequest;
import com.dailyon.auctionservice.repository.AuctionRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
Expand All @@ -26,4 +33,26 @@ public Auction create(CreateAuctionRequest auctionRequest, CreateProductResponse
)
);
}

public Page<Auction> readAuctions(Pageable pageable) {
int currentPage = pageable.getPageNumber();
int pageSize = pageable.getPageSize();

int startIdx = currentPage * pageSize;
int endIdx = startIdx + pageSize;

List<Auction> auctions = (List<Auction>) auctionRepository.findAll();
if(auctions.isEmpty()) {
return new PageImpl<>(new ArrayList<>(), pageable, 0);
}

int totalSize = auctions.size();

List<Auction> sorted = auctions.stream()
.sorted(Auction::compareTo)
.collect(Collectors.toList())
.subList(startIdx, Math.min(endIdx, totalSize));

return new PageImpl<>(sorted, pageable, totalSize);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.springframework.beans.factory.annotation.Autowired;

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

class AuctionRepositoryTests extends ContainerBaseTestSupport {
@Autowired private AmazonDynamoDBAsync dynamoDB;
Expand Down Expand Up @@ -58,5 +59,25 @@ void createAuctionTest() {
assertEquals(5, created.getMaximumWinner());
assertFalse(created.isEnded());
assertNotNull(created.getId());
assertNotNull(created.getCreatedAt());
}

@Test
@DisplayName("경매 전체 목록 조회")
void readAuctionPageTest() {
for(int i=0; i<5; i++) {
auctionRepository.save(Auction.builder()
.auctionProductId((long) i)
.auctionName("TEST_"+i)
.startBidPrice(1000)
.maximumWinner(5)
.startAt(LocalDateTime.now())
.build()
);
}

List<Auction> auctions = (List<Auction>) auctionRepository.findAll();

assertEquals(5, auctions.size());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.dailyon.auctionservice.service;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDBAsync;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.util.TableUtils;
import com.dailyon.auctionservice.ContainerBaseTestSupport;
import com.dailyon.auctionservice.document.Auction;
import com.dailyon.auctionservice.repository.AuctionRepository;
import org.assertj.core.api.BDDAssertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.BDDMockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;

import static org.junit.jupiter.api.Assertions.*;

import java.time.LocalDateTime;
import java.util.stream.IntStream;

public class AuctionServiceTests extends ContainerBaseTestSupport {
@Autowired private AmazonDynamoDBAsync dynamoDB;
@Autowired private DynamoDBMapper dynamoDBMapper;
@Autowired private AuctionRepository auctionRepository;
@Autowired private AuctionService auctionService;

@BeforeEach
void beforeEach() {
CreateTableRequest createTableRequest = dynamoDBMapper
.generateCreateTableRequest(Auction.class)
.withProvisionedThroughput(new ProvisionedThroughput(1L, 1L));

TableUtils.createTableIfNotExists(dynamoDB, createTableRequest);
}

@AfterEach
void afterEach() {
TableUtils.deleteTableIfExists(
dynamoDB,
dynamoDBMapper.generateDeleteTableRequest(Auction.class)
);
}

@Test
@DisplayName("경매 목록 생성 내림차순 기준 정렬 페이지네이션 조회")
void paginationTest() {
for(int i=0; i<10; i++) {
auctionRepository.save(Auction.builder()
.auctionProductId((long) i)
.auctionName("TEST_"+i)
.startBidPrice(1000)
.maximumWinner(5)
.startAt(LocalDateTime.now())
.build()
);
}

Page<Auction> auctions = auctionService.readAuctions(PageRequest.of(0, 5));
assertEquals(10, auctions.getTotalElements());
assertEquals(2, auctions.getTotalPages());
assertEquals(5, auctions.getContent().size());
IntStream.range(1, 5).forEach(i -> {
Auction prev = auctions.getContent().get(i-1);
Auction next = auctions.getContent().get(i);

BDDAssertions
.then(prev.getCreatedAt().isAfter(next.getCreatedAt()))
.isTrue();
});
}
}

0 comments on commit 4c5d46c

Please sign in to comment.