RestService.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.ServiceModel;
  5. using System.ServiceModel.Web;
  6. using System.Text;
  7. using FrameworkBench;
  8. using Revenj.Api;
  9. using Revenj.DomainPatterns;
  10. using Revenj.Serialization;
  11. using Revenj.Utility;
  12. namespace Revenj.Bench
  13. {
  14. [ServiceContract(Namespace = "https://github.com/ngs-doo/revenj")]
  15. public interface IRestService
  16. {
  17. [OperationContract]
  18. [WebGet(UriTemplate = "/plaintext")]
  19. Stream PlainText();
  20. [OperationContract]
  21. [WebGet(UriTemplate = "/json")]
  22. Stream JSON();
  23. [OperationContract]
  24. [WebGet(UriTemplate = "/db")]
  25. Stream SingleQuery();
  26. [OperationContract]
  27. [WebGet(UriTemplate = "/queries/{count}")]
  28. Stream MultipleQueries(string count);
  29. [OperationContract]
  30. [WebGet(UriTemplate = "/updates/{count}")]
  31. Stream Updates(string count);
  32. [OperationContract]
  33. [WebGet(UriTemplate = "/fortunes")]
  34. Stream Fortunes();
  35. }
  36. public class RestService : IRestService
  37. {
  38. private static readonly ChunkedMemoryStream HelloWorld = ChunkedMemoryStream.Static();
  39. private static readonly string[] IDs = new string[10001];
  40. [ThreadStatic]
  41. private static Context Context;
  42. private static Context GetContext(IServiceProvider services)
  43. {
  44. if (Context == null)
  45. Context = new Context(services);
  46. Context.Stream.Reset();
  47. return Context;
  48. }
  49. static RestService()
  50. {
  51. var hwText = Encoding.UTF8.GetBytes("Hello, World!");
  52. HelloWorld.Write(hwText, 0, hwText.Length);
  53. HelloWorld.Position = 0;
  54. for (int i = 0; i < IDs.Length; i++)
  55. IDs[i] = i.ToString();
  56. }
  57. private Random Random = new Random(0);
  58. private readonly IServiceProvider Services;
  59. public RestService(IServiceProvider services)
  60. {
  61. this.Services = services;
  62. }
  63. public Stream PlainText()
  64. {
  65. ThreadContext.Response.ContentType = "text/plain";
  66. return HelloWorld;
  67. }
  68. private Stream ReturnJSON(IJsonObject value, ChunkedMemoryStream cms)
  69. {
  70. value.Serialize(cms);
  71. ThreadContext.Response.ContentType = "application/json";
  72. return cms;
  73. }
  74. public Stream JSON()
  75. {
  76. var ctx = GetContext(Services);
  77. return ReturnJSON(new Message { message = "Hello, World!" }, ctx.Stream);
  78. }
  79. public Stream SingleQuery()
  80. {
  81. var id = Random.Next(10000) + 1;
  82. var ctx = GetContext(Services);
  83. var world = ctx.WorldRepository.Find(IDs[id]);
  84. return ReturnJSON(world, ctx.Stream);
  85. }
  86. private void LoadWorlds(int repeat, Context ctx)
  87. {
  88. var reader = ctx.BulkReader;
  89. var lazyResult = ctx.LazyWorlds;
  90. var worlds = ctx.Worlds;
  91. reader.Reset(true);
  92. for (int i = 0; i < repeat; i++)
  93. {
  94. var id = Random.Next(10000) + 1;
  95. lazyResult[i] = reader.Find<World>(IDs[id]);
  96. }
  97. reader.Execute();
  98. for (int i = 0; i < repeat; i++)
  99. worlds[i] = lazyResult[i].Value;
  100. }
  101. public Stream MultipleQueries(string count)
  102. {
  103. int repeat;
  104. int.TryParse(count, out repeat);
  105. if (repeat < 1) repeat = 1;
  106. else if (repeat > 500) repeat = 500;
  107. var ctx = GetContext(Services);
  108. LoadWorlds(repeat, ctx);
  109. var cms = ctx.Stream;
  110. ctx.Worlds.Serialize(cms, repeat);
  111. ThreadContext.Response.ContentType = "application/json";
  112. return cms;
  113. }
  114. private static readonly Comparison<World> ASC = (l, r) => l.id - r.id;
  115. public Stream Updates(string count)
  116. {
  117. int repeat;
  118. int.TryParse(count, out repeat);
  119. if (repeat < 1) repeat = 1;
  120. else if (repeat > 500) repeat = 500;
  121. var ctx = GetContext(Services);
  122. LoadWorlds(repeat, ctx);
  123. var result = new World[repeat];
  124. Array.Copy(ctx.Worlds, result, repeat);
  125. for (int i = 0; i < result.Length; i++)
  126. result[i].randomNumber = Random.Next(10000) + 1;
  127. Array.Sort(result, ASC);
  128. ctx.WorldRepository.Update(result);
  129. var cms = ctx.Stream;
  130. result.Serialize(cms);
  131. ThreadContext.Response.ContentType = "application/json";
  132. return cms;
  133. }
  134. private static readonly Comparison<KeyValuePair<int, string>> Comparison = (l, r) => string.Compare(l.Value, r.Value, StringComparison.Ordinal);
  135. public Stream Fortunes()
  136. {
  137. var ctx = GetContext(Services);
  138. var fortunes = ctx.FortuneRepository.Search();
  139. var list = new List<KeyValuePair<int, string>>(fortunes.Length + 1);
  140. foreach (var f in fortunes)
  141. list.Add(new KeyValuePair<int, string>(f.id, f.message));
  142. list.Add(new KeyValuePair<int, string>(0, "Additional fortune added at request time."));
  143. list.Sort(Comparison);
  144. var cms = ctx.Stream;
  145. var writer = cms.GetWriter();
  146. var template = new Fortunes(list, writer);
  147. template.TransformText();
  148. writer.Flush();
  149. cms.Position = 0;
  150. ThreadContext.Response.ContentType = "text/html; charset=UTF-8";
  151. return cms;
  152. }
  153. }
  154. }