123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- package controllers;
- import akka.dispatch.ExecutionContexts;
- import models.Fortune;
- import models.World;
- import play.Play;
- import play.core.NamedThreadFactory;
- import play.libs.F;
- import play.libs.Json;
- import play.mvc.Controller;
- import play.mvc.Result;
- import play.mvc.With;
- import scala.concurrent.ExecutionContext;
- import utils.Headers;
- import utils.Predicate;
- import utils.Predicated;
- import java.util.*;
- import java.util.concurrent.LinkedBlockingQueue;
- import java.util.concurrent.ThreadLocalRandom;
- import java.util.concurrent.ThreadPoolExecutor;
- import java.util.concurrent.TimeUnit;
- @With(Headers.class)
- public class Application extends Controller {
- private static final int TEST_DATABASE_ROWS = 10000;
- private static final int partitionCount = Play.application().configuration().getInt("db.default.partitionCount");
- private static final int maxConnections =
- partitionCount * Play.application().configuration().getInt("db.default.maxConnectionsPerPartition");
- private static final int minConnections =
- partitionCount * Play.application().configuration().getInt("db.default.minConnectionsPerPartition");
- private static final ThreadPoolExecutor tpe = new ThreadPoolExecutor(minConnections, maxConnections,
- 0L, TimeUnit.MILLISECONDS,
- new LinkedBlockingQueue<Runnable>(),
- new NamedThreadFactory("dbEc"));
- private static final ExecutionContext dbEc = ExecutionContexts.fromExecutorService(tpe);
- // If the thread-pool used by the database grows too large then our server
- // is probably struggling, and we should start dropping requests. Set
- // the max size of our queue something above the number of concurrent
- // connections that we need to handle.
- public static class IsDbAvailable implements Predicate {
- @Override
- public boolean condition() {
- return tpe.getQueue().size() <= 1024;
- }
- }
- @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE)
- public static F.Promise<Result> db() {
- return getRandomWorlds(1).map(new F.Function<List<World>, Result>() {
- @Override
- public Result apply(List<World> worlds) {
- return ok(Json.toJson(worlds.get(0)));
- }
- });
- }
- @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE)
- public static F.Promise<Result> queries(final String queryCountString) {
- return getRandomWorlds(queryCount(queryCountString)).map(new F.Function<List<World>, Result>() {
- @Override
- public Result apply(List<World> worlds) {
- return ok(Json.toJson(worlds));
- }
- });
- }
- @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE)
- public static F.Promise<Result> fortunes() {
- return F.Promise.promise(new F.Function0<Result>() {
- @Override
- public Result apply() throws Throwable {
- List<Fortune> fortunes = Fortune.find.all();
- fortunes.add(new Fortune("Additional fortune added at request time."));
- Collections.sort(fortunes, new Comparator<Fortune>() {
- @Override
- public int compare(Fortune f1, Fortune f2) {
- return f1.message.compareTo(f2.message);
- }
- });
- return ok(views.html.fortunes.render(fortunes));
- }
- }, dbEc);
- }
- @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE)
- public static F.Promise<Result> update(final String queryCountString) {
- return getRandomWorlds(queryCount(queryCountString)).map(new F.Function<List<World>, Result>() {
- @Override
- public Result apply(List<World> worlds) throws Throwable {
- Random random = ThreadLocalRandom.current();
- for (World world : worlds) {
- world.randomNumber = (long) (random.nextInt(10000) + 1);
- }
- List<World> updatedWorlds = World.save(worlds);
- return ok(Json.toJson(updatedWorlds));
- }
- }, dbEc);
- }
- private static int queryCount(String queryCountString) {
- int queryCount;
- try {
- queryCount = Integer.parseInt(queryCountString, 10);
- } catch (NumberFormatException e) {
- queryCount = 1;
- }
- if (queryCount < 1) {
- queryCount = 1;
- } else if (queryCount > 500) {
- queryCount = 500;
- }
- return queryCount;
- }
- private static F.Promise<List<World>> getRandomWorlds(final int n) {
- return F.Promise.promise(new F.Function0<List<World>>() {
- @Override
- public List<World> apply() {
- Random random = ThreadLocalRandom.current();
- List<World> worlds = new ArrayList<World>(n);
- for (int i = 0; i < n; ++i) {
- long randomId = random.nextInt(TEST_DATABASE_ROWS) + 1;
- World world = World.find.byId(randomId);
- worlds.add(world);
- }
- return worlds;
- }
- }, dbEc);
- }
- }
|