From d1aa06dd959d5de6ad26331ce8bcec0d9a27aae0 Mon Sep 17 00:00:00 2001 From: Andrew Lalis Date: Thu, 26 Jan 2023 14:07:41 +0100 Subject: [PATCH] Added submissions.csv to sample data, and improved concurrency. --- gymboard-api/pom.xml | 3 +- gymboard-api/sample_data/cities.csv | 4 +- gymboard-api/sample_data/submissions.csv | 2 + .../gymboard_api/config/AsyncConfig.java | 14 ----- .../gymboard_api/model/SampleDataLoader.java | 53 ++++++++++++++++--- .../service/ExerciseSubmissionService.java | 13 +++-- .../application-development.properties | 3 ++ 7 files changed, 65 insertions(+), 27 deletions(-) create mode 100644 gymboard-api/sample_data/submissions.csv diff --git a/gymboard-api/pom.xml b/gymboard-api/pom.xml index ab7503e..5f1d41a 100644 --- a/gymboard-api/pom.xml +++ b/gymboard-api/pom.xml @@ -45,7 +45,8 @@ org.springframework.boot spring-boot-starter-test - test + + compile diff --git a/gymboard-api/sample_data/cities.csv b/gymboard-api/sample_data/cities.csv index 283f04b..65dbce9 100644 --- a/gymboard-api/sample_data/cities.csv +++ b/gymboard-api/sample_data/cities.csv @@ -1,2 +1,4 @@ nl,groningen,Groningen -us,tampa,Tampa \ No newline at end of file +nl,amsterdam,Amsterdam +us,tampa,Tampa +us,new-york-city,New York City \ No newline at end of file diff --git a/gymboard-api/sample_data/submissions.csv b/gymboard-api/sample_data/submissions.csv new file mode 100644 index 0000000..344a78f --- /dev/null +++ b/gymboard-api/sample_data/submissions.csv @@ -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 diff --git a/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/config/AsyncConfig.java b/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/config/AsyncConfig.java index 9784500..92dffe2 100644 --- a/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/config/AsyncConfig.java +++ b/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/config/AsyncConfig.java @@ -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; - } } diff --git a/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/model/SampleDataLoader.java b/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/model/SampleDataLoader.java index 672f7b2..95246ad 100644 --- a/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/model/SampleDataLoader.java +++ b/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/model/SampleDataLoader.java @@ -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 { + 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 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); } diff --git a/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/service/ExerciseSubmissionService.java b/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/service/ExerciseSubmissionService.java index 0df8637..af6a601 100644 --- a/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/service/ExerciseSubmissionService.java +++ b/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/service/ExerciseSubmissionService.java @@ -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 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 { *

* @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 optionalSubmission = exerciseSubmissionRepository.findById(submissionId); diff --git a/gymboard-api/src/main/resources/application-development.properties b/gymboard-api/src/main/resources/application-development.properties index 4aea7c8..13bdea4 100644 --- a/gymboard-api/src/main/resources/application-development.properties +++ b/gymboard-api/src/main/resources/application-development.properties @@ -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