-
Notifications
You must be signed in to change notification settings - Fork 1.9k
/
Application.java
121 lines (100 loc) · 4.3 KB
/
Application.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package controllers;
import static models.tables.Fortune.FORTUNE;
import static models.tables.World.WORLD;
import static play.mvc.Http.MimeTypes.JSON;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ThreadLocalRandom;
import javax.inject.Inject;
import org.jooq.DSLContext;
import org.jooq.JSONFormat;
import org.jooq.JSONFormat.RecordFormat;
import org.jooq.SQLDialect;
import org.jooq.impl.DSL;
import org.jooq.types.UInteger;
import models.tables.records.FortuneRecord;
import models.tables.records.WorldRecord;
import play.db.Database;
import play.mvc.Controller;
import play.mvc.Result;
import utils.DatabaseExecutionContext;
public class Application extends Controller {
private static final SQLDialect DIALECT = SQLDialect.MYSQL_5_7;
private static final JSONFormat JSON_FORMAT = JSONFormat.DEFAULT_FOR_RECORDS.recordFormat(RecordFormat.OBJECT);
private final Database db;
private final DatabaseExecutionContext dbEc;
@Inject
public Application(final Database db, final DatabaseExecutionContext dbEc) {
this.db = db;
this.dbEc = dbEc;
}
public CompletionStage<Result> db() {
return getRandomWorlds(1).thenApply(worlds -> ok(worlds.get(0).formatJSON(JSON_FORMAT)).as(JSON));
}
public CompletionStage<Result> queries(final String queries) {
return getRandomWorlds(queryCount(queries)).thenApply(worlds -> ok(worlds.formatJSON(JSON_FORMAT)).as(JSON));
}
public CompletionStage<Result> fortunes() {
return CompletableFuture.supplyAsync(() -> {
final List<FortuneRecord> fortunes = this.db.withConnection(connection -> {
return DSL.using(connection, DIALECT).select(FORTUNE.ID, FORTUNE.MESSAGE).from(FORTUNE).fetchInto(FortuneRecord.class);
});
fortunes.add(new FortuneRecord(UInteger.valueOf(0), "Additional fortune added at request time."));
Collections.sort(fortunes, (f1, f2) -> f1.getMessage().compareTo(f2.getMessage()));
return ok(views.html.fortunes.render(fortunes));
}, dbEc);
}
public CompletionStage<Result> update(final String queries) {
return getRandomWorlds(queryCount(queries)).thenApplyAsync(worlds -> {
final Random random = ThreadLocalRandom.current();
for (final WorldRecord world : worlds) {
world.setRandomnumber((random.nextInt(10000) + 1));
}
final int batchSize = 25;
final int batches = ((worlds.size() / batchSize) + 1);
this.db.withConnection(connection -> {
final DSLContext sql = DSL.using(connection, DIALECT);
for ( int i = 0 ; i < batches ; ++i ) {
sql.batchUpdate(worlds.subList(i * batchSize, Math.min((i + 1) * batchSize, worlds.size()))).execute();
}
return null;
});
return ok(worlds.formatJSON(JSON_FORMAT)).as(JSON);
}, dbEc);
}
private int queryCount(final String queryCountString) {
int queryCount;
try {
queryCount = Integer.parseInt(queryCountString, 10);
} catch (final NumberFormatException e) {
queryCount = 1;
}
if (queryCount < 1) {
queryCount = 1;
} else if (queryCount > 500) {
queryCount = 500;
}
return queryCount;
}
private CompletionStage<org.jooq.Result<WorldRecord>> getRandomWorlds(final int n) {
return CompletableFuture.supplyAsync(() -> {
final Random random = ThreadLocalRandom.current();
org.jooq.Result<WorldRecord> worlds = null;
for (int i = 0; i < n; ++i) {
long randomId = random.nextInt(10000) + 1;
final org.jooq.Result<WorldRecord> world = this.db.withConnection(connection -> {
return DSL.using(connection, DIALECT).selectFrom(WORLD).where(WORLD.ID.eq(UInteger.valueOf(randomId))).fetch();
});
if(worlds == null) {
worlds = world;
} else {
worlds.add(world.get(0));
}
}
return worlds;
}, dbEc);
}
}