mongodb.d 3.9 KB

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