Skip to content

Commit

Permalink
Move servers to database
Browse files Browse the repository at this point in the history
  • Loading branch information
rtm516 committed Jun 25, 2024
1 parent 3a41bce commit 9e6c244
Show file tree
Hide file tree
Showing 13 changed files with 190 additions and 90 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.rtm516.mcxboxbroadcast.manager;

import com.rtm516.mcxboxbroadcast.manager.database.model.Server;
import com.rtm516.mcxboxbroadcast.manager.database.model.User;
import com.rtm516.mcxboxbroadcast.manager.database.repository.ServerCollection;
import com.rtm516.mcxboxbroadcast.manager.database.repository.UserCollection;
import org.java_websocket.util.NamedThreadFactory;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -16,18 +18,26 @@
public class BackendManager {
private final ScheduledExecutorService scheduledThreadPool;
private final UserCollection userCollection;
private final ServerCollection serverCollection;

@Autowired
public BackendManager(UserCollection userCollection, PasswordEncoder passwordEncoder) {
public BackendManager(UserCollection userCollection, PasswordEncoder passwordEncoder, ServerCollection serverCollection) {
this.userCollection = userCollection;
this.serverCollection = serverCollection;

// TODO Allow configuration of thread pool size
this.scheduledThreadPool = Executors.newScheduledThreadPool(Math.max(1, Runtime.getRuntime().availableProcessors() * 3 / 8), new NamedThreadFactory("MCXboxBroadcast Manager Thread"));

this.userCollection = userCollection;

// Create the admin user if it doesn't exist
if (authEnabled() && userCollection.findUserByUsername("admin").isEmpty()) {
userCollection.save(new User("admin", passwordEncoder.encode("password")));
}

// Create the default server if it doesn't exist
if (serverCollection.count() == 0) {
serverCollection.save(new Server("test.geysermc.org", 19132));
}
}

public ScheduledExecutorService scheduledThreadPool() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.rtm516.mcxboxbroadcast.manager;

import com.rtm516.mcxboxbroadcast.core.SessionInfo;
import com.rtm516.mcxboxbroadcast.manager.controllers.BotsController;
import com.rtm516.mcxboxbroadcast.manager.database.model.Bot;
import com.rtm516.mcxboxbroadcast.manager.database.repository.BotCollection;
import com.rtm516.mcxboxbroadcast.manager.database.repository.ServerCollection;
import com.rtm516.mcxboxbroadcast.manager.models.BotContainer;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -20,9 +20,10 @@ public class BotManager {
private final ServerManager serverManager;
private final BackendManager backendManager;
private final BotCollection botCollection;
private final ServerCollection serverCollection;

@Autowired
public BotManager(ServerManager serverManager, BackendManager backendManager, BotCollection botCollection) {
public BotManager(ServerManager serverManager, BackendManager backendManager, BotCollection botCollection, ServerCollection serverCollection) {
this.serverManager = serverManager;
this.backendManager = backendManager;
this.botCollection = botCollection;
Expand All @@ -38,6 +39,7 @@ public BotManager(ServerManager serverManager, BackendManager backendManager, Bo
botContainer.start();
}
});
this.serverCollection = serverCollection;
}

public BotCollection botCollection() {
Expand All @@ -52,12 +54,12 @@ public String logs(ObjectId botId) {
return bots.get(botId).logs();
}

public SessionInfo serverSessionInfo(int id) {
public SessionInfo serverSessionInfo(ObjectId id) {
return serverManager.servers().get(id).sessionInfo();
}

public BotContainer addBot() {
Bot bot = botCollection.save(new Bot());
Bot bot = botCollection.save(new Bot(serverManager.firstServer()));

BotContainer botContainer = new BotContainer(this, bot);
bots.put(bot._id(), botContainer);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.rtm516.mcxboxbroadcast.manager;

import com.rtm516.mcxboxbroadcast.manager.models.Server;
import com.rtm516.mcxboxbroadcast.manager.database.model.Server;
import com.rtm516.mcxboxbroadcast.manager.database.repository.ServerCollection;
import com.rtm516.mcxboxbroadcast.manager.models.ServerContainer;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
Expand All @@ -11,36 +14,49 @@
@Service
@Scope
public class ServerManager {
private final Map<ObjectId, ServerContainer> servers = new HashMap<>();
private final BackendManager backendManager;

private Map<Integer, Server> servers = new HashMap<>();
private final ServerCollection serverCollection;

@Autowired
public ServerManager(BackendManager backendManager) {
public ServerManager(BackendManager backendManager, ServerCollection serverCollection) {
this.backendManager = backendManager;

// String hostName, String worldName, String version, int protocol, int players, int maxPlayers, String ip, int port
servers.put(0, new Server(0, "test.geysermc.org", 19132));
// Load all servers from the database
serverCollection.findAll().forEach(server -> {
servers.put(server._id(), new ServerContainer(server));
});

// Start the bots in a new thread so the web server can start
backendManager.scheduledThreadPool().execute(() -> {
for (Server server : servers.values()) {
server.updateSessionInfo();
for (ServerContainer serverContainer : servers.values()) {
serverContainer.updateSessionInfo();
}
});
this.serverCollection = serverCollection;
}

public Map<Integer, Server> servers() {
public Map<ObjectId, ServerContainer> servers() {
return servers;
}

public Server addServer() {
Server server = new Server(servers.size(), "mc.example.com", 19132);
servers.put(server.id(), server);
return server;
public ServerContainer addServer() {
Server server = serverCollection.save(new Server("mc.example.com", 19132));

ServerContainer serverContainer = new ServerContainer(server);
servers.put(server._id(), serverContainer);
return serverContainer;
}

public void deleteServer(int serverId) {
public void deleteServer(ObjectId serverId) {
servers.remove(serverId);
}

public ObjectId firstServer() {
if (!servers.isEmpty()) {
return servers.values().iterator().next().server()._id();
}

return addServer().server()._id();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,13 @@ public void update(HttpServletResponse response, @PathVariable ObjectId botId, @
return;
}

// Update the server ID and save the bot to the database
// Update the server ID then save the bot to the database
BotContainer botContainer = botManager.bots().get(botId);
botContainer.bot().serverId(botUpdateRequest.serverId());
botCollection.save(botContainer.bot());

backendManager.scheduledThreadPool().execute(() -> botContainer.updateSessionInfo()); // Update the session info in a new thread
// Update the session info in a new thread
backendManager.scheduledThreadPool().execute(botContainer::updateSessionInfo);

response.setStatus(200);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

import com.rtm516.mcxboxbroadcast.manager.BackendManager;
import com.rtm516.mcxboxbroadcast.manager.ServerManager;
import com.rtm516.mcxboxbroadcast.manager.models.Server;
import com.rtm516.mcxboxbroadcast.manager.database.repository.ServerCollection;
import com.rtm516.mcxboxbroadcast.manager.models.ServerContainer;
import com.rtm516.mcxboxbroadcast.manager.models.request.ServerUpdateRequest;
import com.rtm516.mcxboxbroadcast.manager.models.response.ServerInfoResponse;
import jakarta.servlet.http.HttpServletResponse;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
Expand All @@ -22,38 +25,40 @@ public class ServersController {

private final ServerManager serverManager;
private final BackendManager backendManager;
private final ServerCollection serverCollection;

@Autowired
public ServersController(ServerManager serverManager, BackendManager backendManager) {
public ServersController(ServerManager serverManager, BackendManager backendManager, ServerCollection serverCollection) {
this.serverManager = serverManager;
this.backendManager = backendManager;
this.serverCollection = serverCollection;
}

@GetMapping("")
public List<Server> servers(HttpServletResponse response) {
public List<ServerInfoResponse> servers(HttpServletResponse response) {
response.setStatus(200);
return serverManager.servers().values().stream().toList();
return serverManager.servers().values().stream().map(ServerContainer::toResponse).toList();
}

@PostMapping("/create")
public int create(HttpServletResponse response) {
public ObjectId create(HttpServletResponse response) {
response.setStatus(200);
Server server = serverManager.addServer();
return server.id();
ServerContainer serverContainer = serverManager.addServer();
return serverContainer.server()._id();
}

@GetMapping("/{serverId:[0-9]+}")
public Server server(HttpServletResponse response, @PathVariable int serverId) {
@GetMapping("/{serverId:[a-z0-9]+}")
public ServerInfoResponse server(HttpServletResponse response, @PathVariable ObjectId serverId) {
if (!serverManager.servers().containsKey(serverId)) {
response.setStatus(404);
return null;
}
response.setStatus(200);
return serverManager.servers().get(serverId);
return serverManager.servers().get(serverId).toResponse();
}

@PostMapping("/{serverId:[0-9]+}")
public void update(HttpServletResponse response, @PathVariable int serverId, @RequestBody ServerUpdateRequest serverUpdateRequest) {
@PostMapping("/{serverId:[a-z0-9]+}")
public void update(HttpServletResponse response, @PathVariable ObjectId serverId, @RequestBody ServerUpdateRequest serverUpdateRequest) {
if (!serverManager.servers().containsKey(serverId)) {
response.setStatus(404);
return;
Expand All @@ -69,16 +74,20 @@ public void update(HttpServletResponse response, @PathVariable int serverId, @Re
return;
}

serverManager.servers().get(serverId).hostname(serverUpdateRequest.hostname());
serverManager.servers().get(serverId).port(serverUpdateRequest.port());
// Update the hostname and port then save the server to the database
ServerContainer serverContainer = serverManager.servers().get(serverId);
serverContainer.server().hostname(serverUpdateRequest.hostname());
serverContainer.server().port(serverUpdateRequest.port());
serverCollection.save(serverContainer.server());

backendManager.scheduledThreadPool().execute(() -> serverManager.servers().get(serverId).updateSessionInfo()); // Update the session info in a new thread
// Update the session info in a new thread
backendManager.scheduledThreadPool().execute(serverContainer::updateSessionInfo);

response.setStatus(200);
}

@DeleteMapping("/{serverId:[0-9]+}")
public void delete(HttpServletResponse response, @PathVariable int serverId) {
@DeleteMapping("/{serverId:[a-z0-9]+}")
public void delete(HttpServletResponse response, @PathVariable ObjectId serverId) {
if (!serverManager.servers().containsKey(serverId)) {
response.setStatus(404);
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,9 @@ public class Bot {
private ObjectId _id;
private String gamertag;
private String xid;
private int serverId;
private ObjectId serverId;

public Bot() {
this(0);
}

public Bot(int serverId) {
public Bot(ObjectId serverId) {
this.gamertag = "";
this.xid = "";
this.serverId = serverId;
Expand All @@ -44,11 +40,11 @@ public void xid(String xid) {
this.xid = xid;
}

public int serverId() {
public ObjectId serverId() {
return serverId;
}

public void serverId(int serverId) {
public void serverId(ObjectId serverId) {
this.serverId = serverId;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.rtm516.mcxboxbroadcast.manager.database.model;

import com.rtm516.mcxboxbroadcast.core.SessionInfo;
import com.rtm516.mcxboxbroadcast.manager.models.response.ServerInfoResponse;
import org.bson.types.ObjectId;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

import java.util.Date;

@Document("servers")
public class Server {
@Id
private ObjectId _id;
private String hostname;
private int port;

public Server(String hostname, int port) {
this.hostname = hostname;
this.port = port;
}

public ObjectId _id() {
return _id;
}

public String hostname() {
return hostname;
}

public void hostname(String hostname) {
this.hostname = hostname;
}

public int port() {
return port;
}

public void port(int port) {
this.port = port;
}

public ServerInfoResponse toResponse(SessionInfo sessionInfo, Date lastUpdated) {
return new ServerInfoResponse(_id.toString(), hostname, port, sessionInfo, lastUpdated);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.rtm516.mcxboxbroadcast.manager.database.repository;

import com.rtm516.mcxboxbroadcast.manager.database.model.Server;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ServerCollection extends MongoRepository<Server, ObjectId> {
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,16 @@ public BotInfoResponse toResponse() {
public void start() {
status = Status.STARTING;
logger = new Logger(this); // TODO Move to file based?
sessionManager = new SessionManager("./cache/" + bot()._id(), logger);
sessionManager = new SessionManager("./cache/" + bot._id(), logger);

sessionManager.restartCallback(this::restart);
try {
sessionManager.init(botManager.serverSessionInfo(bot().serverId()), new FriendSyncConfig(20, true, true));
sessionManager.init(botManager.serverSessionInfo(bot.serverId()), new FriendSyncConfig(20, true, true));
status = Status.ONLINE;

bot().gamertag(sessionManager.getGamertag());
bot().xid(sessionManager.getXuid());
botManager.botCollection().save(bot());
bot.gamertag(sessionManager.getGamertag());
bot.xid(sessionManager.getXuid());
botManager.botCollection().save(bot);

sessionManager.scheduledThread().scheduleWithFixedDelay(this::updateSessionInfo, 30, 30, TimeUnit.SECONDS);
} catch (SessionCreationException | SessionUpdateException e) {
Expand All @@ -79,7 +79,7 @@ public void updateSessionInfo() {

try {
// Update the session
sessionManager.updateSession(botManager.serverSessionInfo(bot().serverId()));
sessionManager.updateSession(botManager.serverSessionInfo(bot.serverId()));
sessionManager.logger().info("Updated session!");
} catch (SessionUpdateException e) {
sessionManager.logger().error("Failed to update session", e);
Expand Down
Loading

0 comments on commit 9e6c244

Please sign in to comment.