update mojang endpoint to include the name of the service
All checks were successful
Deploy App / docker (ubuntu-latest, 2.44.0, 17, 3.8.5) (push) Successful in 2m18s

This commit is contained in:
Lee 2024-04-19 17:21:10 +01:00
parent 03c679d25c
commit 8a985b52b8
3 changed files with 55 additions and 55 deletions

@ -12,6 +12,7 @@ import xyz.mcutils.backend.common.CachedResponse;
import xyz.mcutils.backend.model.mojang.EndpointStatus; import xyz.mcutils.backend.model.mojang.EndpointStatus;
import java.io.Serializable; import java.io.Serializable;
import java.util.List;
@Setter @Getter @ToString @Setter @Getter @ToString
@RedisHash(value = "mojangEndpointStatus", timeToLive = 60L) // 1 minute (in seconds) @RedisHash(value = "mojangEndpointStatus", timeToLive = 60L) // 1 minute (in seconds)
@ -26,12 +27,11 @@ public class CachedEndpointStatus extends CachedResponse implements Serializable
/** /**
* The endpoint cache. * The endpoint cache.
*/ */
@JsonUnwrapped private final List<EndpointStatus> endpoints;
private final EndpointStatus value;
public CachedEndpointStatus(@NonNull String id, EndpointStatus value) { public CachedEndpointStatus(@NonNull String id, List<EndpointStatus> endpoints) {
super(Cache.defaultCache()); super(Cache.defaultCache());
this.id = id; this.id = id;
this.value = value; this.endpoints = endpoints;
} }
} }

@ -2,18 +2,33 @@ package xyz.mcutils.backend.model.mojang;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import java.util.Map; import java.util.Map;
@AllArgsConstructor @RequiredArgsConstructor
@Getter @Getter @Setter
public class EndpointStatus { public class EndpointStatus {
/** /**
* The list of endpoints and their status. * The name of the service.
*/ */
private final Map<String, Status> endpoints; private final String name;
/**
* The hostname of the service.
*/
private final String hostname;
/**
* The status of the service.
*/
private Status status;
/**
* Statuses for the endpoint.
*/
public enum Status { public enum Status {
/** /**
* The service is online and operational. * The service is online and operational.

@ -10,24 +10,21 @@ import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpirationPolicy;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import xyz.mcutils.backend.Main; import xyz.mcutils.backend.common.*;
import xyz.mcutils.backend.common.Endpoint;
import xyz.mcutils.backend.common.EnvironmentUtils;
import xyz.mcutils.backend.common.ExpiringSet;
import xyz.mcutils.backend.common.WebRequest;
import xyz.mcutils.backend.model.cache.CachedEndpointStatus; import xyz.mcutils.backend.model.cache.CachedEndpointStatus;
import xyz.mcutils.backend.model.mojang.EndpointStatus; import xyz.mcutils.backend.model.mojang.EndpointStatus;
import xyz.mcutils.backend.model.token.MojangProfileToken; import xyz.mcutils.backend.model.token.MojangProfileToken;
import xyz.mcutils.backend.model.token.MojangUsernameToUuidToken; import xyz.mcutils.backend.model.token.MojangUsernameToUuidToken;
import xyz.mcutils.backend.repository.redis.EndpointStatusRepository; import xyz.mcutils.backend.repository.redis.EndpointStatusRepository;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.InetAddress;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.*; import java.util.*;
import java.util.Timer;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -56,15 +53,14 @@ public class MojangService {
* Information about the Mojang API endpoints. * Information about the Mojang API endpoints.
*/ */
private static final String MOJANG_ENDPOINT_STATUS_KEY = "mojang"; private static final String MOJANG_ENDPOINT_STATUS_KEY = "mojang";
private static final List<Endpoint> MOJANG_ENDPOINTS = List.of( private static final List<EndpointStatus> MOJANG_ENDPOINTS = List.of(
new Endpoint("https://textures.minecraft.net", List.of(HttpStatus.BAD_REQUEST)), new EndpointStatus("Minecraft Textures", "textures.minecraft.net"),
new Endpoint("https://session.minecraft.net", List.of(HttpStatus.NOT_FOUND)), new EndpointStatus("Minecraft Session", "session.minecraft.net"),
new Endpoint("https://libraries.minecraft.net", List.of(HttpStatus.NOT_FOUND)), new EndpointStatus("Minecraft Libraries", "libraries.minecraft.net"),
new Endpoint("https://assets.mojang.com", List.of(HttpStatus.NOT_FOUND)), new EndpointStatus("Minecraft Services", "api.minecraftservices.com"),
new Endpoint("https://api.minecraftservices.com", List.of(HttpStatus.FORBIDDEN)), new EndpointStatus("Mojang Assets", "assets.mojang.com"),
new Endpoint(API_ENDPOINT, List.of(HttpStatus.OK)), new EndpointStatus("Mojang API", API_ENDPOINT),
new Endpoint(SESSION_SERVER_ENDPOINT, List.of(HttpStatus.FORBIDDEN)) new EndpointStatus("Mojang Session Server", SESSION_SERVER_ENDPOINT));
);
@Autowired @Autowired
private EndpointStatusRepository mojangEndpointStatusRepository; private EndpointStatusRepository mojangEndpointStatusRepository;
@ -195,43 +191,32 @@ public class MojangService {
return endpointStatus.get(); return endpointStatus.get();
} }
// Fetch the status of the Mojang API endpoints List<CompletableFuture<Void>> futures = new ArrayList<>();
List<CompletableFuture<EndpointStatus.Status>> futures = new ArrayList<>(); for (EndpointStatus endpoint : MOJANG_ENDPOINTS) {
for (Endpoint endpoint : MOJANG_ENDPOINTS) { futures.add(CompletableFuture.runAsync(() -> {
CompletableFuture<EndpointStatus.Status> future = CompletableFuture.supplyAsync(() -> { try {
boolean online = false; long start = System.currentTimeMillis();
long start = System.currentTimeMillis(); InetAddress address = InetAddress.getByName(endpoint.getHostname());
ResponseEntity<?> response = WebRequest.head(endpoint.getEndpoint(), String.class); if (address.isReachable(5000)) { // Check if the endpoint is reachable
if (endpoint.getAllowedStatuses().contains(response.getStatusCode())) { endpoint.setStatus(EndpointStatus.Status.ONLINE);
online = true; return;
}
// Check if the endpoint took too long to respond
if (System.currentTimeMillis() - start > TimeUnit.SECONDS.toMillis(2)) {
endpoint.setStatus(EndpointStatus.Status.DEGRADED);
}
} catch (IOException e) {
endpoint.setStatus(EndpointStatus.Status.OFFLINE);
} }
if (online && System.currentTimeMillis() - start > 1000) { // If the response took longer than 1 second }));
return EndpointStatus.Status.DEGRADED;
}
return online ? EndpointStatus.Status.ONLINE : EndpointStatus.Status.OFFLINE;
}, Main.EXECUTOR_POOL);
futures.add(future);
}
CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
try {
allFutures.get(5, TimeUnit.SECONDS); // Wait for the futures to complete
} catch (Exception e) {
log.error("Timeout while fetching Mojang API status: {}", e.getMessage());
} }
// Process the results CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
Map<String, EndpointStatus.Status> endpoints = new HashMap<>();
for (int i = 0; i < MOJANG_ENDPOINTS.size(); i++) {
Endpoint endpoint = MOJANG_ENDPOINTS.get(i);
EndpointStatus.Status status = futures.get(i).join();
endpoints.put(endpoint.getEndpoint(), status);
}
log.info("Fetched Mojang API status for {} endpoints", endpoints.size()); log.info("Fetched Mojang API status for {} endpoints", MOJANG_ENDPOINTS.size());
CachedEndpointStatus status = new CachedEndpointStatus( CachedEndpointStatus status = new CachedEndpointStatus(
MOJANG_ENDPOINT_STATUS_KEY, MOJANG_ENDPOINT_STATUS_KEY,
new EndpointStatus(endpoints) MOJANG_ENDPOINTS
); );
mojangEndpointStatusRepository.save(status); mojangEndpointStatusRepository.save(status);
status.getCache().setCached(false); status.getCache().setCached(false);