BlobService.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. using Azure;
  2. using Azure.Cosmos;
  3. using Azure.Messaging.ServiceBus;
  4. using Azure.Storage.Blobs;
  5. using DocumentFormat.OpenXml.Wordprocessing;
  6. using HTEXLib.COMM.Helpers;
  7. using Microsoft.Extensions.Configuration;
  8. using StackExchange.Redis;
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Linq;
  12. using System.Text;
  13. using System.Text.Json;
  14. using System.Threading.Tasks;
  15. using TEAMModelOS.SDK.DI;
  16. using TEAMModelOS.SDK.Extension;
  17. namespace TEAMModelOS.SDK.Services
  18. {
  19. public static class BlobService
  20. {
  21. public static async Task RefreshBlobRoot(BlobRefreshMessage message, AzureServiceBusFactory _serviceBus,IConfiguration _configuration,AzureRedisFactory _azureRedis) {
  22. if (!string.IsNullOrWhiteSpace(message.root) && !string.IsNullOrWhiteSpace(message.name)) {
  23. string lockKey = $"Blob:Lock:{message.name}:{message.root}";
  24. bool exist = await _azureRedis.GetRedisClient(8).KeyExistsAsync(lockKey);
  25. //不存在Blob:Lock:hbcn:video 文件夹在队列中 则加入队列
  26. if (!exist)
  27. {
  28. //保持一天的时间
  29. TimeSpan timeSpan = new TimeSpan(1,0,0);
  30. //加入队列的时间
  31. long action = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  32. await _azureRedis.GetRedisClient(8).StringSetAsync(lockKey, action, expiry: timeSpan);
  33. var messageBlob = new ServiceBusMessage(message.ToJsonString());
  34. messageBlob.ApplicationProperties.Add("name", "BlobRoot");
  35. var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
  36. await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);
  37. }
  38. //如果已经存在,则忽略,不加入队列。
  39. }
  40. }
  41. public static async Task<UsedBlob> GetBlobUsed(CosmosClient clientc, BlobContainerClient clients, IDatabase clientr, string scope, string containerName)
  42. {
  43. UsedBlob result = new UsedBlob();
  44. try
  45. {
  46. //学校已经分配给所有教师的空间大小GB。
  47. long teach = 0;
  48. if (scope.Equals("school"))
  49. {
  50. await foreach (var item in clientc.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: $"SELECT sum(c.size) as size FROM c ",
  51. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Teacher-{containerName}") }))
  52. {
  53. var json = await JsonDocument.ParseAsync(item.ContentStream);
  54. foreach (var elmt in json.RootElement.GetProperty("Documents").EnumerateArray())
  55. {
  56. if (elmt.TryGetProperty("size", out JsonElement _size) && _size.ValueKind.Equals(JsonValueKind.Number))
  57. {
  58. teach = _size.GetInt32();
  59. break;
  60. }
  61. }
  62. }
  63. }
  64. //使用blob狀況
  65. bool getBlobCatalogFromBlob = false; //是否直接去blob取得使用狀況 false:否(Redis) true:是(Blob)
  66. long blobsize = 0;
  67. RedisValue value = default;
  68. value = clientr.HashGet($"Blob:Record", containerName);
  69. if (value != default && !value.IsNullOrEmpty)
  70. {
  71. JsonElement record = value.ToString().ToObject<JsonElement>();
  72. if (record.TryGetInt64(out blobsize))
  73. {
  74. }
  75. else
  76. {
  77. getBlobCatalogFromBlob = true;
  78. }
  79. }
  80. else
  81. {
  82. getBlobCatalogFromBlob = true;
  83. }
  84. Dictionary<string, double?> catalog = new Dictionary<string, double?>();
  85. SortedSetEntry[] Scores = clientr.SortedSetRangeByScoreWithScores($"Blob:Catalog:{containerName}");
  86. if (Scores != null)
  87. {
  88. foreach (var score in Scores)
  89. {
  90. double val = score.Score;
  91. string key = score.Element.ToString();
  92. catalog.Add(key, val);
  93. }
  94. }
  95. if (!getBlobCatalogFromBlob)
  96. {
  97. result.size = blobsize;
  98. result.catalog = catalog;
  99. result.teach = teach;
  100. return result;
  101. }
  102. else
  103. {
  104. var size = await clients.GetBlobsCatalogSize();
  105. result.size = size.Item1;
  106. result.catalog = size.Item2;
  107. result.teach = teach;
  108. return result;
  109. }
  110. }
  111. catch (Exception ex)
  112. {
  113. //await _dingDing.SendBotMsg($"CoreAPI2,{_option.Location},Channel/Create()\n{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  114. return result;
  115. }
  116. }
  117. /// <param name="scope">school or private</param>
  118. /// <param name="containerName">school code or tmid</param>
  119. /// <param name="type">doc, res, item... Empty if no need.</param>
  120. /// <param name="periodId">Only for school</param>
  121. public static async Task<List<BlobCount>> BloblogCount(CosmosClient clientc, string scope, string containerName, string type, string periodId)
  122. {
  123. List<BlobCount> bloblogcnt = new List<BlobCount>();
  124. try
  125. {
  126. //必須項檢查
  127. if(scope.Equals("school") && string.IsNullOrWhiteSpace(periodId))
  128. {
  129. return bloblogcnt;
  130. }
  131. //資料取得
  132. var queryslt = new StringBuilder();
  133. queryslt.Append($"SELECT COUNT(1) AS count, c.type FROM c ");
  134. if (scope.Equals("school"))
  135. {
  136. queryslt.Append($"JOIN A1 IN c.periodId WHERE A1 IN ('{periodId}') ");
  137. if(!string.IsNullOrWhiteSpace(type)) queryslt.Append($"AND c.type='{type}'");
  138. queryslt.Append("GROUP BY c.type");
  139. await foreach (var item in clientc.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<BlobCount>(queryText: queryslt.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Bloblog-{containerName}") }))
  140. {
  141. bloblogcnt.Add(item);
  142. }
  143. }
  144. else if (scope.Equals("private"))
  145. {
  146. if (!string.IsNullOrWhiteSpace(type)) queryslt.Append($"AND c.type='{type}'");
  147. queryslt.Append("GROUP BY c.type");
  148. await foreach (var item in clientc.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<BlobCount>(queryText: queryslt.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Bloblog-{containerName}") }))
  149. {
  150. bloblogcnt.Add(item);
  151. }
  152. }
  153. return bloblogcnt;
  154. }
  155. catch (Exception ex)
  156. {
  157. return bloblogcnt;
  158. }
  159. }
  160. public class UsedBlob
  161. {
  162. public long teach { get; set; }
  163. public long? size { get; set; }
  164. public Dictionary<string, double?> catalog { get; set; }
  165. }
  166. public class BlobCount
  167. {
  168. public string type { get; set; }
  169. public int count { get; set; }
  170. }
  171. }
  172. public class BlobRefreshMessage{
  173. public string id { get; set; }= Guid.NewGuid().ToString();
  174. public string name { get; set; }
  175. public string progress { get; set; }
  176. public string root { get; set; }
  177. }
  178. }