Skip to content

Commit 4307a3d

Browse files
committed
Bouncer restart job
1 parent 6454169 commit 4307a3d

8 files changed

Lines changed: 152 additions & 13 deletions

File tree

README.MD

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,14 @@ Java application designed to automate various backend tasks we have within Parad
66

77
It handles:
88

9+
- Bouncer Restart
910
- Profiler Daemon Ingest
1011
- Profiler DB Cleanup
1112

13+
### Bouncer Restart
14+
15+
Restarts our "bouncer" server every day. This is the thing that does 2FA, server queue, and region redirection.
16+
1217
### Profiler Daemon Ingest
1318

1419
This takes BYOND Profiler results and split them apart to be indexed at a later date, allowing multiple procs from multiple rounds to easily be visualised alongside eachother over time. An example SS13 codebase implementation can be found at <https://github.com/ParadiseSS13/Paradise/pull/17459>.
@@ -33,16 +38,15 @@ To build, run `mvn package` to generate the JAR file. This will then appear in t
3338
1. Compile the codebase (See `Building`).
3439
2. Copy the jar and the example `config.toml` in the repository root to a running location.
3540
3. Import the `schemas/profiler_schema.sql` schema to your database server.
36-
4. Setup the configuration to specify the relevant information:
41+
4. Setup the configuration as per section labels.
3742
5. Start the application up, it will now run tasks in the background.
3843

39-
Or just use the dockerfile.
40-
4144
## Code Guidelines
4245

43-
- Code must be tested
44-
- Code must adhere to the style guidelines set in `checkstyle.xml`
45-
- These are google's guidelines but with minor tweaks for my own needs
46+
- Code must be tested.
47+
- Good luck.
48+
- Code must adhere to the style guidelines set in `checkstyle.xml`.
49+
- These are google's guidelines but with minor tweaks for my own needs.
4650

4751
## License
4852

TaskDaemon.Core/src/me/aa07/paradise/taskdaemon/core/Core.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import java.util.Optional;
66
import me.aa07.paradise.taskdaemon.core.config.ConfigHolder;
77
import me.aa07.paradise.taskdaemon.core.database.DbCore;
8+
import me.aa07.paradise.taskdaemon.core.modules.bouncerrestart.BouncerRestartJob;
89
import me.aa07.paradise.taskdaemon.core.modules.profilercleanup.ProfilerCleanupJob;
910
import me.aa07.paradise.taskdaemon.core.modules.profileringest.ProfilerWorker;
1011
import me.aa07.paradise.taskdaemon.core.redis.RedisManager;
@@ -68,17 +69,30 @@ private void setupThreads(ConfigHolder config, Logger logger) {
6869
// Launch Quartz
6970
try {
7071
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
71-
setupJobs(scheduler, database, logger);
72+
setupJobs(scheduler, database, config, logger);
7273
scheduler.start();
7374
} catch (SchedulerException ex) {
7475
logger.error("Quartz had a hissy fit!", ex);
7576
}
7677
}
7778

78-
private void setupJobs(Scheduler scheduler, DbCore dbCore, Logger logger) throws SchedulerException {
79+
private void setupJobs(Scheduler scheduler, DbCore dbCore, ConfigHolder config, Logger logger) throws SchedulerException {
7980
// See below for CRON format
8081
// https://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html
8182

83+
// Bouncer restart
84+
JobDataMap jdm_bouncerrestart = new JobDataMap();
85+
jdm_bouncerrestart.put("LOGGER", logger);
86+
jdm_bouncerrestart.put("TGS_CFG", config.tgs);
87+
JobDetail jd_bouncerrestart = JobBuilder.newJob(BouncerRestartJob.class)
88+
.withIdentity("bouncerrestart", "bouncerrestart")
89+
.usingJobData(jdm_bouncerrestart)
90+
.build();
91+
CronTrigger ct_bouncerrestart = TriggerBuilder.newTrigger()
92+
.withIdentity("bouncerrestart", "bouncerrestart")
93+
.withSchedule(CronScheduleBuilder.cronSchedule("0 0 0 * * ?")) // Every day - midnight
94+
.build();
95+
8296
// Profiler cleanup
8397
JobDataMap jdm_profilercleanup = new JobDataMap();
8498
jdm_profilercleanup.put("LOGGER", logger);
@@ -94,6 +108,7 @@ private void setupJobs(Scheduler scheduler, DbCore dbCore, Logger logger) throws
94108

95109

96110
// Schedule all
111+
scheduler.scheduleJob(jd_bouncerrestart, ct_bouncerrestart);
97112
scheduler.scheduleJob(jd_profilercleanup, ct_profilercleanup);
98113
}
99114

TaskDaemon.Core/src/me/aa07/paradise/taskdaemon/core/config/ConfigHolder.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
public class ConfigHolder {
44
public DatabaseConfig profilerDatabase;
55
public RedisConfig redis;
6+
public TgsConfig tgs;
67
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package me.aa07.paradise.taskdaemon.core.config;
2+
3+
public class TgsConfig {
4+
public String tgsHost;
5+
public String username;
6+
public String password;
7+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package me.aa07.paradise.taskdaemon.core.models.tgs;
2+
3+
public class TokenResponseModel {
4+
public String bearer;
5+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package me.aa07.paradise.taskdaemon.core.modules.bouncerrestart;
2+
3+
import com.google.gson.Gson;
4+
import java.net.URI;
5+
import java.net.http.HttpClient;
6+
import java.net.http.HttpRequest;
7+
import java.net.http.HttpResponse;
8+
import java.net.http.HttpResponse.BodyHandlers;
9+
import java.nio.charset.StandardCharsets;
10+
import java.util.Base64;
11+
import java.util.Optional;
12+
import me.aa07.paradise.taskdaemon.core.config.TgsConfig;
13+
import me.aa07.paradise.taskdaemon.core.models.tgs.TokenResponseModel;
14+
import org.apache.logging.log4j.Logger;
15+
import org.quartz.DisallowConcurrentExecution;
16+
import org.quartz.Job;
17+
import org.quartz.JobDataMap;
18+
import org.quartz.JobExecutionContext;
19+
import org.quartz.JobExecutionException;
20+
21+
@DisallowConcurrentExecution // NO
22+
public class BouncerRestartJob implements Job {
23+
24+
@Override
25+
public void execute(JobExecutionContext event) throws JobExecutionException {
26+
JobDataMap datamap = event.getMergedJobDataMap();
27+
28+
// Get our logger - important
29+
Object raw_logger = datamap.get("LOGGER");
30+
Optional<Logger> logger_holder = Optional.empty();
31+
32+
if (raw_logger instanceof Logger l2) {
33+
logger_holder = Optional.of(l2);
34+
}
35+
36+
if (!logger_holder.isPresent()) {
37+
System.out.println("[BouncerRestart] LOGGER WAS SOMEHOW NULL - THIS IS VERY BAD");
38+
return;
39+
}
40+
41+
Logger logger = logger_holder.get();
42+
43+
// Now get our TGS config
44+
Object raw_tgs_cfg = datamap.get("TGS_CFG");
45+
Optional<TgsConfig> tgs_cfg_holder = Optional.empty();
46+
47+
if (raw_tgs_cfg instanceof TgsConfig tgsCfg) {
48+
tgs_cfg_holder = Optional.of(tgsCfg);
49+
}
50+
51+
if (!tgs_cfg_holder.isPresent()) {
52+
logger.error("[BouncerRestart] TGS_CFG WAS SOMEHOW NULL - THIS IS VERY BAD");
53+
return;
54+
}
55+
56+
logger.info("[BouncerRestart] Generating TGS creds");
57+
58+
TgsConfig tgs_cfg = tgs_cfg_holder.get();
59+
60+
// Now do the actual TGS requesting stuff
61+
String creds = String.format("%s:%s", tgs_cfg.username, tgs_cfg.password);
62+
byte[] encoded_auth = Base64.getEncoder().encode(creds.getBytes(StandardCharsets.UTF_8));
63+
String auth_header = String.format("Basic %s", new String(encoded_auth));
64+
65+
// This needs to be in try/catch
66+
try {
67+
// Get our auth token first
68+
HttpRequest httpreq = HttpRequest.newBuilder().uri(new URI(String.format("%s/api", tgs_cfg.tgsHost)))
69+
.POST(HttpRequest.BodyPublishers.noBody())
70+
.setHeader("Accept", "application/json")
71+
.setHeader("Content-Type", "application/json")
72+
.setHeader("Api", "Tgstation.Server.Api/10.0.0")
73+
.setHeader("Authorization", auth_header).build();
74+
75+
HttpClient client = HttpClient.newHttpClient();
76+
logger.info("[BouncerRestart] Sending auth token request");
77+
HttpResponse<String> response = client.send(httpreq, BodyHandlers.ofString());
78+
79+
Gson gson = new Gson();
80+
TokenResponseModel tokres = gson.fromJson(response.body(), TokenResponseModel.class);
81+
82+
// And send our restart request
83+
HttpRequest httreq2 = HttpRequest.newBuilder()
84+
.uri(new URI(String.format("%s/api/DreamDaemon", tgs_cfg.tgsHost)))
85+
.method("PATCH", HttpRequest.BodyPublishers.noBody())
86+
.setHeader("Accept", "application/json")
87+
.setHeader("Content-Type", "application/json")
88+
.setHeader("Instance", "2")
89+
.setHeader("Api", "Tgstation.Server.Api/10.0.0")
90+
.setHeader("Authorization", String.format("Bearer %s", tokres.bearer)).build();
91+
92+
HttpClient client2 = HttpClient.newHttpClient();
93+
logger.info("[BouncerRestart] Sending restart request");
94+
client2.send(httreq2, BodyHandlers.ofString());
95+
} catch (Exception e) {
96+
logger.error("Error in BouncerRestartJob!");
97+
logger.error(e);
98+
}
99+
100+
logger.info("[BouncerRestart] Done");
101+
}
102+
}

TaskDaemon.Core/src/me/aa07/paradise/taskdaemon/core/modules/profilercleanup/ProfilerCleanupJob.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public void execute(JobExecutionContext event) throws JobExecutionException {
2727
}
2828

2929
if (!logger_holder.isPresent()) {
30-
System.out.println("LOGGER WAS SOMEHOW NULL - THIS IS VERY BAD");
30+
System.out.println("[ProfilerCleanup] LOGGER WAS SOMEHOW NULL - THIS IS VERY BAD");
3131
return;
3232
}
3333

@@ -42,19 +42,19 @@ public void execute(JobExecutionContext event) throws JobExecutionException {
4242
}
4343

4444
if (!dbcore_holder.isPresent()) {
45-
logger.error("DBCORE WAS SOMEHOW NULL - THIS IS VERY BAD");
45+
logger.error("[ProfilerCleanup] DBCORE WAS SOMEHOW NULL - THIS IS VERY BAD");
4646
return;
4747
}
4848

4949
DbCore dbcore = dbcore_holder.get();
5050

51-
logger.info("Cleaning out profiler DB - proc samples");
51+
logger.info("[ProfilerCleanup] Cleaning out profiler DB - proc samples");
5252
dbcore.jooq(DatabaseType.ProfilerDb).delete(Tables.SAMPLES)
5353
.where(Tables.SAMPLES.SAMPLETIME.lt(dbcore.now().minusDays(7))).execute();
54-
logger.info("Cleaning out profiler DB - sendmaps samples");
54+
logger.info("[ProfilerCleanup] Cleaning out profiler DB - sendmaps samples");
5555
dbcore.jooq(DatabaseType.ProfilerDb).delete(Tables.SENDMAPS_SAMPLES)
5656
.where(Tables.SENDMAPS_SAMPLES.SAMPLETIME.lt(dbcore.now().minusDays(7))).execute();
57-
logger.info("Cleaned");
57+
logger.info("[ProfilerCleanup] Cleaned");
5858
}
5959

6060
}

config.toml.example

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,8 @@ database = "paradise_profilerdaemon"
88

99
[redis]
1010
host = "172.16.0.200"
11+
12+
[tgs]
13+
tgsHost = "http://10.0.0.30:5000" # dont put a trailing slash on the end of this
14+
username = "username_here"
15+
password = "password_here"

0 commit comments

Comments
 (0)