You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

CachedRestClient.cs 4.3 kB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Net;
  5. using System.Reactive.Concurrency;
  6. using System.Reactive.Linq;
  7. using System.Threading;
  8. using System.Threading.Tasks;
  9. using Akavache;
  10. using Akavache.Sqlite3;
  11. using Discord.Net.Rest;
  12. using Splat;
  13. namespace Discord.Net
  14. {
  15. internal class CachedRestClient : IRestClient
  16. {
  17. private readonly IBlobCache _blobCache;
  18. private readonly CancellationTokenSource _cancelTokenSource;
  19. private readonly Dictionary<string, string> _headers;
  20. private string _baseUrl;
  21. private CancellationToken _cancelToken, _parentToken;
  22. private bool _isDisposed;
  23. public CachedRestClient()
  24. {
  25. _headers = new Dictionary<string, string>();
  26. _cancelTokenSource = new CancellationTokenSource();
  27. _cancelToken = CancellationToken.None;
  28. _parentToken = CancellationToken.None;
  29. Locator.CurrentMutable.Register(() => Scheduler.Default, typeof(IScheduler), "Taskpool");
  30. Locator.CurrentMutable.Register(() => new FilesystemProvider(), typeof(IFilesystemProvider));
  31. Locator.CurrentMutable.Register(() => new HttpMixin(), typeof(IAkavacheHttpMixin));
  32. //new Akavache.Sqlite3.Registrations().Register(Locator.CurrentMutable);
  33. _blobCache = new SQLitePersistentBlobCache("cache.db");
  34. }
  35. public CacheInfo Info { get; private set; }
  36. public void SetHeader(string key, string value) => _headers[key] = value;
  37. public void SetCancelToken(CancellationToken cancelToken)
  38. {
  39. _parentToken = cancelToken;
  40. _cancelToken = CancellationTokenSource.CreateLinkedTokenSource(_parentToken, _cancelTokenSource.Token)
  41. .Token;
  42. }
  43. public async Task<RestResponse> SendAsync(string method, string endpoint, CancellationToken cancelToken,
  44. bool headerOnly, string reason = null)
  45. {
  46. if (method != "GET")
  47. throw new InvalidOperationException("This RestClient only supports GET requests.");
  48. var uri = Path.Combine(_baseUrl, endpoint);
  49. var bytes = await _blobCache.DownloadUrl(uri, _headers);
  50. return new RestResponse(HttpStatusCode.OK, _headers, new MemoryStream(bytes));
  51. }
  52. public Task<RestResponse> SendAsync(string method, string endpoint, string json, CancellationToken cancelToken,
  53. bool headerOnly, string reason = null) =>
  54. throw new InvalidOperationException("This RestClient does not support payloads.");
  55. public Task<RestResponse> SendAsync(string method, string endpoint,
  56. IReadOnlyDictionary<string, object> multipartParams, CancellationToken cancelToken, bool headerOnly,
  57. string reason = null) =>
  58. throw new InvalidOperationException("This RestClient does not support multipart requests.");
  59. private void Dispose(bool disposing)
  60. {
  61. if (_isDisposed) return;
  62. if (disposing)
  63. _blobCache.Dispose();
  64. _isDisposed = true;
  65. }
  66. public void Dispose() => Dispose(true);
  67. public void SetUrl(string url) => _baseUrl = url;
  68. public async Task ClearAsync() => await _blobCache.InvalidateAll();
  69. public async Task LoadInfoAsync(ulong guildId)
  70. {
  71. if (Info != null)
  72. return;
  73. var needsReset = false;
  74. try
  75. {
  76. Info = await _blobCache.GetObject<CacheInfo>("info");
  77. if (Info.GuildId != guildId)
  78. needsReset = true;
  79. }
  80. catch (KeyNotFoundException)
  81. {
  82. needsReset = true;
  83. }
  84. if (needsReset)
  85. {
  86. Info = new CacheInfo
  87. {
  88. GuildId = guildId,
  89. Version = 0
  90. };
  91. await SaveInfoAsync().ConfigureAwait(false);
  92. }
  93. }
  94. public async Task SaveInfoAsync()
  95. {
  96. await ClearAsync().ConfigureAwait(false); //Version changed, invalidate cache
  97. await _blobCache.InsertObject("info", Info);
  98. }
  99. }
  100. }