Added submissions.csv to sample data, and improved concurrency.
This commit is contained in:
parent
3908c2becd
commit
d1aa06dd95
|
@ -45,7 +45,8 @@
|
|||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
<!-- TODO: Change this to "test" once the SampleDataLoader is refactored to the tests. -->
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
nl,groningen,Groningen
|
||||
nl,amsterdam,Amsterdam
|
||||
us,tampa,Tampa
|
||||
us,new-york-city,New York City
|
|
|
@ -0,0 +1,2 @@
|
|||
barbell-overhead-press,60,KG,1,Andrew Lalis,nl_groningen_trainmore-munnekeholm,sample_video_ohp.mp4
|
||||
incline-dumbbell-bicep-curl,14,KG,10,Andrew Lalis,nl_groningen_trainmore-munnekeholm,sample_video_curl.mp4
|
|
|
@ -1,25 +1,11 @@
|
|||
package nl.andrewlalis.gymboard_api.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
@Configuration
|
||||
@EnableAsync
|
||||
@EnableScheduling
|
||||
public class AsyncConfig {
|
||||
@Bean
|
||||
public Executor taskExecutor() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
executor.setCorePoolSize(3);
|
||||
executor.setMaxPoolSize(5);
|
||||
executor.setQueueCapacity(100);
|
||||
executor.setThreadNamePrefix("gymboard-api-");
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,25 @@
|
|||
package nl.andrewlalis.gymboard_api.model;
|
||||
|
||||
import nl.andrewlalis.gymboard_api.controller.dto.CompoundGymId;
|
||||
import nl.andrewlalis.gymboard_api.controller.dto.ExerciseSubmissionPayload;
|
||||
import nl.andrewlalis.gymboard_api.dao.CityRepository;
|
||||
import nl.andrewlalis.gymboard_api.dao.CountryRepository;
|
||||
import nl.andrewlalis.gymboard_api.dao.GymRepository;
|
||||
import nl.andrewlalis.gymboard_api.dao.exercise.ExerciseRepository;
|
||||
import nl.andrewlalis.gymboard_api.model.exercise.Exercise;
|
||||
import nl.andrewlalis.gymboard_api.model.exercise.ExerciseSubmission;
|
||||
import nl.andrewlalis.gymboard_api.service.ExerciseSubmissionService;
|
||||
import nl.andrewlalis.gymboard_api.service.UploadService;
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.commons.csv.CSVRecord;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
|
@ -31,17 +38,21 @@ public class SampleDataLoader implements ApplicationListener<ContextRefreshedEve
|
|||
private final CityRepository cityRepository;
|
||||
private final GymRepository gymRepository;
|
||||
private final ExerciseRepository exerciseRepository;
|
||||
private final ExerciseSubmissionService submissionService;
|
||||
private final UploadService uploadService;
|
||||
|
||||
public SampleDataLoader(
|
||||
CountryRepository countryRepository,
|
||||
CityRepository cityRepository,
|
||||
GymRepository gymRepository,
|
||||
ExerciseRepository exerciseRepository
|
||||
) {
|
||||
ExerciseRepository exerciseRepository,
|
||||
ExerciseSubmissionService submissionService, UploadService uploadService) {
|
||||
this.countryRepository = countryRepository;
|
||||
this.cityRepository = cityRepository;
|
||||
this.gymRepository = gymRepository;
|
||||
this.exerciseRepository = exerciseRepository;
|
||||
this.submissionService = submissionService;
|
||||
this.uploadService = uploadService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -84,10 +95,40 @@ public class SampleDataLoader implements ApplicationListener<ContextRefreshedEve
|
|||
record.get(7)
|
||||
));
|
||||
});
|
||||
loadCsv("submissions", record -> {
|
||||
var exercise = exerciseRepository.findById(record.get(0)).orElseThrow();
|
||||
BigDecimal weight = new BigDecimal(record.get(1));
|
||||
ExerciseSubmission.WeightUnit unit = ExerciseSubmission.WeightUnit.valueOf(record.get(2).toUpperCase());
|
||||
int reps = Integer.parseInt(record.get(3));
|
||||
String name = record.get(4);
|
||||
CompoundGymId gymId = CompoundGymId.parse(record.get(5));
|
||||
String videoFilename = record.get(6);
|
||||
|
||||
try {
|
||||
var uploadResp = uploadService.handleSubmissionUpload(gymId, new MockMultipartFile(
|
||||
videoFilename,
|
||||
videoFilename,
|
||||
"video/mp4",
|
||||
Files.readAllBytes(Path.of("sample_data", videoFilename))
|
||||
));
|
||||
submissionService.createSubmission(gymId, new ExerciseSubmissionPayload(
|
||||
name,
|
||||
exercise.getShortName(),
|
||||
weight.floatValue(),
|
||||
unit.name(),
|
||||
reps,
|
||||
uploadResp.id()
|
||||
));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void loadCsv(String csvName, Consumer<CSVRecord> recordConsumer) throws IOException {
|
||||
var reader = new FileReader("sample_data/" + csvName + ".csv");
|
||||
String path = "sample_data/" + csvName + ".csv";
|
||||
log.info("Loading data from {}...", path);
|
||||
var reader = new FileReader(path);
|
||||
for (var record : CSVFormat.DEFAULT.parse(reader)) {
|
||||
recordConsumer.accept(record);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ import nl.andrewlalis.gymboard_api.model.exercise.ExerciseSubmissionVideoFile;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
@ -33,6 +32,7 @@ import java.time.Instant;
|
|||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
|
@ -49,19 +49,23 @@ public class ExerciseSubmissionService {
|
|||
private final ExerciseSubmissionRepository exerciseSubmissionRepository;
|
||||
private final ExerciseSubmissionTempFileRepository tempFileRepository;
|
||||
private final ExerciseSubmissionVideoFileRepository submissionVideoFileRepository;
|
||||
private final Executor taskExecutor;
|
||||
|
||||
public ExerciseSubmissionService(GymRepository gymRepository,
|
||||
StoredFileRepository fileRepository,
|
||||
ExerciseRepository exerciseRepository,
|
||||
ExerciseSubmissionRepository exerciseSubmissionRepository,
|
||||
ExerciseSubmissionTempFileRepository tempFileRepository,
|
||||
ExerciseSubmissionVideoFileRepository submissionVideoFileRepository) {
|
||||
ExerciseSubmissionVideoFileRepository submissionVideoFileRepository,
|
||||
Executor taskExecutor
|
||||
) {
|
||||
this.gymRepository = gymRepository;
|
||||
this.fileRepository = fileRepository;
|
||||
this.exerciseRepository = exerciseRepository;
|
||||
this.exerciseSubmissionRepository = exerciseSubmissionRepository;
|
||||
this.tempFileRepository = tempFileRepository;
|
||||
this.submissionVideoFileRepository = submissionVideoFileRepository;
|
||||
this.taskExecutor = taskExecutor;
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
|
@ -132,7 +136,7 @@ public class ExerciseSubmissionService {
|
|||
public void processWaitingSubmissions() {
|
||||
List<ExerciseSubmission> waitingSubmissions = exerciseSubmissionRepository.findAllByStatus(ExerciseSubmission.Status.WAITING);
|
||||
for (var submission : waitingSubmissions) {
|
||||
processSubmission(submission.getId());
|
||||
taskExecutor.execute(() -> processSubmission(submission.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,8 +150,7 @@ public class ExerciseSubmissionService {
|
|||
* </p>
|
||||
* @param submissionId The submission's id.
|
||||
*/
|
||||
@Async
|
||||
public void processSubmission(long submissionId) {
|
||||
private void processSubmission(long submissionId) {
|
||||
log.info("Starting processing of submission {}.", submissionId);
|
||||
// First try and fetch the submission.
|
||||
Optional<ExerciseSubmission> optionalSubmission = exerciseSubmissionRepository.findById(submissionId);
|
||||
|
|
|
@ -5,3 +5,6 @@ spring.datasource.url=jdbc:postgresql://localhost:5432/gymboard-api-dev
|
|||
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
spring.jpa.show-sql=false
|
||||
|
||||
spring.task.execution.pool.core-size=3
|
||||
spring.task.execution.pool.max-size=10
|
||||
|
|
Loading…
Reference in New Issue