[Updated] Dockerfiles so everything runs using docker compose up, added the benchmark and speed tests
This commit is contained in:
+13
-2
@@ -16,11 +16,22 @@ ENV USER=dev
|
||||
RUN groupadd -g ${GID} ${USER} \
|
||||
&& useradd -m -u ${UID} -g ${USER} ${USER}
|
||||
USER ${USER}
|
||||
EXPOSE 8080
|
||||
EXPOSE 9090
|
||||
CMD ["tail","-f","/dev/null"]
|
||||
|
||||
#---Building
|
||||
FROM base AS build
|
||||
COPY . .
|
||||
RUN mvn clean package -DskipTests
|
||||
|
||||
|
||||
#--Testing
|
||||
FROM build AS testing
|
||||
RUN mvn clean test
|
||||
|
||||
#---Production
|
||||
# Pulled again to get rid of maven, to decrease the size
|
||||
FROM openjdk:17-jdk-slim AS production
|
||||
WORKDIR /app
|
||||
COPY --from=build /app/target/*.jar app.jar
|
||||
EXPOSE 9090
|
||||
ENTRYPOINT ["java", "-jar", "app.jar"]
|
||||
@@ -23,6 +23,14 @@ public class QuizController {
|
||||
@Autowired
|
||||
private QuizService quizService;
|
||||
|
||||
/**
|
||||
* Start a session
|
||||
* @param amount The amount of questsions
|
||||
* @param category The desired category (or all)
|
||||
* @param difficulty The desired difficulty (or all)
|
||||
* @param type The desired type (or both)
|
||||
* @return The sessionId, or statusCode 5 when the queue is full
|
||||
*/
|
||||
@GetMapping("/questions")
|
||||
public String startSession(
|
||||
@RequestParam(required = true) Integer amount,
|
||||
@@ -40,11 +48,21 @@ public class QuizController {
|
||||
return jsonString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the questions have been retrieved
|
||||
* @param sessionId The session that holds the questions
|
||||
* @return The Session, or nothing if they are not ready yet
|
||||
*/
|
||||
@GetMapping("/status/{sessionId}")
|
||||
public Optional<Session> checkStatus(@PathVariable String sessionId) {
|
||||
return quizService.checkSession(sessionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive the chosen answers, calculate the score, and return it
|
||||
* @param answers The chosen answers
|
||||
* @return The score
|
||||
*/
|
||||
@PostMapping("/score")
|
||||
public String checkAnswers(@RequestBody Answers answers) {
|
||||
String jsonString = String.format("{\"score\":\"%s\"}", quizService.getScore(answers));
|
||||
|
||||
@@ -48,4 +48,21 @@ public class ApiService {
|
||||
logger.log(System.Logger.Level.ERROR, "Critical failure", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect a chuck of 50 items
|
||||
* Store them in the DataService
|
||||
*/
|
||||
public void collectBulk() {
|
||||
String url = apiUrl + "?amount=50";
|
||||
try {
|
||||
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
|
||||
String json = response.getBody();
|
||||
ApiResponse apiResponse = cleanerService.extractApiResponse(json);
|
||||
responseHandler.handleResponse(apiResponse);
|
||||
|
||||
} catch (RestClientException | IOException e) {
|
||||
logger.log(System.Logger.Level.ERROR, "Critical failure", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public class ResponseHandlingService {
|
||||
|
||||
switch (response.getResponseCode()) {
|
||||
case 0:
|
||||
// Nothing
|
||||
// Success
|
||||
updateSessionInCache(session, response);
|
||||
break;
|
||||
case 1:
|
||||
@@ -58,7 +58,7 @@ public class ResponseHandlingService {
|
||||
/**
|
||||
* If the request was made by the scheduler during queue-downtime, there is no session
|
||||
*/
|
||||
public void switchInternal(ApiResponse response) {
|
||||
public void handleResponse(ApiResponse response) {
|
||||
switch (response.getResponseCode()) {
|
||||
case 0:
|
||||
// TODO: Store in DB
|
||||
|
||||
@@ -30,7 +30,7 @@ public class ApiServiceTest {
|
||||
@Test
|
||||
public void testRequestQuestions() throws Exception {
|
||||
QuizSettings settings = new QuizSettings();
|
||||
String jsonResponse = apiService.requestQuestions(settings);
|
||||
String jsonResponse = apiService.handleRequest(settings);
|
||||
JsonNode jsonNode = objectMapper.readTree(jsonResponse);
|
||||
|
||||
// Check if the response code is as expected
|
||||
|
||||
@@ -8,3 +8,12 @@ services:
|
||||
container_name: quiz-frontend-prod-cont
|
||||
ports:
|
||||
- "4200:80"
|
||||
backend:
|
||||
build:
|
||||
context: ./backend
|
||||
dockerfile: Dockerfile
|
||||
target: production
|
||||
image: quiz-backend-prod
|
||||
container_name: quiz-backend-prod-cont
|
||||
ports:
|
||||
- "9090:9090"
|
||||
+1
-1
@@ -22,7 +22,7 @@ COPY package*.json ./
|
||||
RUN npm install
|
||||
# Copied here, since the the Development setup uses a bind volume instead
|
||||
COPY . .
|
||||
RUN npm run build --prod
|
||||
RUN ng build --configuration production
|
||||
|
||||
#--- Production
|
||||
FROM nginx:alpine AS production
|
||||
|
||||
@@ -50,6 +50,12 @@
|
||||
"maximumError": "4kB"
|
||||
}
|
||||
],
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"outputHashing": "all"
|
||||
},
|
||||
"development": {
|
||||
|
||||
@@ -18,12 +18,13 @@ import { Answers } from '../models/answers';
|
||||
import { StorageService } from './storage.service';
|
||||
import { CleanerService } from './cleaner.service';
|
||||
import { ResponseHandlerService } from './response-handler.service';
|
||||
import { environment } from '../../../environments/environment';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class QuizService {
|
||||
private apiUrl = 'http://localhost:9090/quiz';
|
||||
private apiUrl = environment.apiUrl + '/quiz';
|
||||
|
||||
constructor(
|
||||
private http: HttpClient,
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
export const environment = {
|
||||
production: true,
|
||||
/** Connecting through the docker compose network is not working for now, so I'll have to use the localhost */
|
||||
// apiUrl: 'http://backend:9090',
|
||||
apiUrl: 'http://localhost:9090',
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
export const environment = {
|
||||
production: false,
|
||||
apiUrl: 'http://localhost:9090'
|
||||
};
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
start_time=$(date +%s)
|
||||
|
||||
for i in {1..6}; do
|
||||
./LoadTestOne.sh &
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
wait # Wait for all background jobs to finish
|
||||
|
||||
end_time=$(date +%s) # Capture the end time
|
||||
|
||||
# Calculate and print the elapsed time
|
||||
elapsed_time=$((end_time - start_time))
|
||||
echo "Done!"
|
||||
echo "Total time taken: $elapsed_time seconds"
|
||||
Executable
+37
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Step 1: Get the sessionId from the questions endpoint
|
||||
sessionIdJson=$(curl -s http://localhost:9090/quiz/questions?amount=5)
|
||||
|
||||
statusCode=$(echo "$sessionIdJson" | grep -o '"statusCode":[0-9]*' | sed 's/"statusCode"://')
|
||||
|
||||
if [ "$statusCode" -ne 0 ]; then
|
||||
echo "Exiting: statusCode is not 0."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sessionId=$(echo "$sessionIdJson" | grep -o '"sessionId":"[^"]*"' | sed 's/"sessionId":"//;s/"//')
|
||||
|
||||
if [ -z "$sessionId" ]; then
|
||||
echo "Failed to get sessionId"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Received sessionId: $sessionId"
|
||||
|
||||
# Step 2: Poll the status endpoint every 2 seconds
|
||||
while true; do
|
||||
status_response=$(curl -s http://localhost:9090/quiz/status/"$sessionId")
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
# Check if the response is JSON (starts with '{')
|
||||
if [[ $status_response == \{* ]]; then
|
||||
echo "$sessionId: done!"
|
||||
break
|
||||
fi
|
||||
else
|
||||
echo "Status check failed, retrying..."
|
||||
fi
|
||||
|
||||
sleep 2
|
||||
done
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 62 KiB |
Reference in New Issue
Block a user