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