mongodb.d 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. import vibe.db.mongo.mongo;
  2. import vibe.http.router;
  3. import vibe.http.server;
  4. import vibe.web.web;
  5. import std.conv : ConvException, to;
  6. import std.random : uniform;
  7. import std.array;
  8. enum worldSize = 10000;
  9. shared static this()
  10. {
  11. auto router = new URLRouter;
  12. router.registerWebInterface(new WebInterface);
  13. router.rebuild();
  14. auto settings = new HTTPServerSettings;
  15. settings.bindAddresses = ["0.0.0.0"];
  16. settings.options |= HTTPServerOption.distribute;
  17. settings.port = 8080;
  18. listenHTTP(settings, router);
  19. }
  20. MongoCollection _worldCollection;
  21. MongoCollection _fortuneCollection;
  22. // sets up the MongoDB connection pools for each thread
  23. static this()
  24. {
  25. import std.process : environment;
  26. auto db = connectMongoDB(environment["DBHOST"]);
  27. _worldCollection = db.getCollection("hello_world.World");
  28. _fortuneCollection = db.getCollection("hello_world.Fortune");
  29. }
  30. class WebInterface {
  31. // GET /
  32. void get()
  33. {
  34. render!"index.dt";
  35. }
  36. // GET /json
  37. void getJson(HTTPServerResponse res)
  38. {
  39. // NOTE: the status and content type parameters are optional, but we need
  40. // to specify them, because the default content type is "application/json; charset=UTF8"
  41. res.writeJsonBody(Message("Hello, World!"), HTTPStatus.ok, "application/json");
  42. }
  43. // GET /db
  44. void getDB(HTTPServerResponse res)
  45. {
  46. struct Q { int _id; }
  47. auto query = Q(uniform(1, worldSize + 1));
  48. auto w = WorldResponse(_worldCollection.findOne!World(query));
  49. res.writeJsonBody(w, HTTPStatus.ok, "application/json");
  50. }
  51. // GET /queries?queries=...
  52. void getQueries(HTTPServerResponse res, string queries)
  53. {
  54. import std.algorithm : min, max;
  55. // Convert the "queries" parameter to int and ignore any conversion errors
  56. // Note that you'd usually declare queries as int instead. However, the
  57. // test required to gracefully handle errors here.
  58. int count = 1;
  59. try count = min(max(queries.to!int, 1), 500);
  60. catch (ConvException) {}
  61. // assemble the response array
  62. scope data = new WorldResponse[count];
  63. foreach (ref w; data) {
  64. static struct Q { int _id; }
  65. auto query = Q(uniform(1, worldSize + 1));
  66. w = WorldResponse(_worldCollection.findOne!World(query));
  67. }
  68. // write response as JSON
  69. res.writeJsonBody(data, HTTPStatus.ok, "application/json");
  70. }
  71. // GET /fortunes
  72. void getFortunes()
  73. {
  74. import std.algorithm : map, sort;
  75. FortuneResponse[] data;
  76. data = _fortuneCollection.find!Fortune().map!(f => FortuneResponse(f)).array;
  77. data ~= FortuneResponse(Fortune(0, "Additional fortune added at request time."));
  78. data.sort!((a, b) => a.message < b.message);
  79. render!("fortunes.dt", data);
  80. }
  81. // GET /updates?queries=...
  82. void getUpdates(HTTPServerResponse res, string queries)
  83. {
  84. import std.algorithm : min, max;
  85. int count = 1;
  86. try count = min(max(queries.to!int, 1), 500);
  87. catch (ConvException e) {}
  88. scope data = new WorldResponse[count];
  89. foreach (ref w; data) {
  90. static struct Q { int _id; }
  91. auto query = Q(uniform(1, worldSize + 1));
  92. w = WorldResponse(_worldCollection.findOne!World(query));
  93. // update random number
  94. w.randomNumber = uniform(1, worldSize+1);
  95. // persist to DB
  96. static struct US {
  97. double randomNumber;
  98. }
  99. static struct U {
  100. @name("$set") US set;
  101. }
  102. _worldCollection.update(query, U(US(w.randomNumber)));
  103. }
  104. // write response as JSON
  105. res.writeJsonBody(data, HTTPStatus.ok, "application/json");
  106. }
  107. // GET /plaintext
  108. void getPlaintext(HTTPServerResponse res)
  109. {
  110. res.writeBody("Hello, World!", HTTPStatus.ok, "text/plain");
  111. }
  112. }
  113. struct Message {
  114. string message;
  115. }
  116. struct World {
  117. double _id;
  118. double randomNumber;
  119. }
  120. struct Fortune {
  121. double _id;
  122. string message;
  123. }
  124. struct WorldResponse {
  125. this(World w) { this.id = cast(int)w._id; this.randomNumber = cast(int)w.randomNumber; }
  126. int id;
  127. int randomNumber;
  128. }
  129. struct FortuneResponse {
  130. this(Fortune f) { this.id = cast(int)f._id; this.message = f.message; }
  131. int id;
  132. string message;
  133. }