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