From 7d88493a547158102f82a41d79ad3332f3e3e6a1 Mon Sep 17 00:00:00 2001 From: Suphonchai Phoonsawat Date: Mon, 27 Jan 2025 13:32:57 +0700 Subject: [PATCH] =?UTF-8?q?fix=20issue=20:=20=E0=B8=A3=E0=B8=B0=E0=B8=9A?= =?UTF-8?q?=E0=B8=9A=E0=B8=A5=E0=B8=87=E0=B9=80=E0=B8=A7=E0=B8=A5=E0=B8=B2?= =?UTF-8?q?=E0=B8=95=E0=B9=89=E0=B8=AD=E0=B8=87=E0=B8=A1=E0=B8=B5=E0=B8=81?= =?UTF-8?q?=E0=B8=B2=E0=B8=A3=E0=B9=80=E0=B8=8A=E0=B9=87=E0=B8=84=E0=B8=AA?= =?UTF-8?q?=E0=B8=96=E0=B8=B2=E0=B8=99=E0=B8=B0=E0=B9=83=E0=B8=99=20rabbit?= =?UTF-8?q?MQ=20=E0=B8=94=E0=B9=89=E0=B8=A7=E0=B8=A2=E0=B8=A7=E0=B9=88?= =?UTF-8?q?=E0=B8=B2=E0=B8=A1=E0=B8=B5=E0=B8=81=E0=B8=B2=E0=B8=A3=E0=B8=A3?= =?UTF-8?q?=E0=B8=AD=E0=B8=A3=E0=B8=B1=E0=B8=99=E0=B8=AD=E0=B8=A2=E0=B8=B9?= =?UTF-8?q?=E0=B9=88=E0=B9=84=E0=B8=AB=E0=B8=A1=20=E0=B8=A5=E0=B8=87?= =?UTF-8?q?=E0=B9=80=E0=B8=A7=E0=B8=A5=E0=B8=B2=E0=B9=80=E0=B8=82=E0=B9=89?= =?UTF-8?q?=E0=B8=B2/=E0=B8=AD=E0=B8=AD=E0=B8=81=E0=B8=87=E0=B8=B2?= =?UTF-8?q?=E0=B8=99=20#894?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BMA.EHR.Leave/Controllers/LeaveController.cs | 195 ++++++++++++++++--- BMA.EHR.Leave/Program.cs | 2 + BMA.EHR.Leave/appsettings.json | 3 +- 3 files changed, 175 insertions(+), 25 deletions(-) diff --git a/BMA.EHR.Leave/Controllers/LeaveController.cs b/BMA.EHR.Leave/Controllers/LeaveController.cs index a742dcc2..9f915104 100644 --- a/BMA.EHR.Leave/Controllers/LeaveController.cs +++ b/BMA.EHR.Leave/Controllers/LeaveController.cs @@ -20,10 +20,12 @@ using Microsoft.Extensions.ObjectPool; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using RabbitMQ.Client; +using RabbitMQ.Client.Events; using Swashbuckle.AspNetCore.Annotations; using System.ComponentModel.DataAnnotations; using System.Security.Claims; using System.Text; +using System.Threading.Tasks; using SearchProfileResultDto = BMA.EHR.Leave.Service.DTOs.ChangeRound.SearchProfileResultDto; namespace BMA.EHR.Leave.Service.Controllers @@ -63,6 +65,8 @@ namespace BMA.EHR.Leave.Service.Controllers private readonly string _fakeCheckInQueue = "fake-bma-checkin-queue"; private readonly string _realCheckInQueue = "bma-checkin-queue"; + private readonly HttpClient _httpClient; + #endregion #region " Constuctor and Destructor " @@ -83,7 +87,8 @@ namespace BMA.EHR.Leave.Service.Controllers LeaveRequestRepository leaveRequestRepository, ObjectPool objectPool, PermissionRepository permission, - NotificationRepository notificationRepository) + NotificationRepository notificationRepository, + HttpClient httpClient) { _dutyTimeRepository = dutyTimeRepository; _context = context; @@ -103,6 +108,13 @@ namespace BMA.EHR.Leave.Service.Controllers _objectPool = objectPool; _permission = permission; + + _httpClient = httpClient; + var authString = $"{_configuration["Rabbit:User"] ?? ""}:{_configuration["Rabbit:Password"] ?? ""}"; + + var authToken = Convert.ToBase64String(Encoding.ASCII.GetBytes(authString)); + _httpClient.DefaultRequestHeaders.Authorization = + new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", authToken); } #endregion @@ -446,7 +458,7 @@ namespace BMA.EHR.Leave.Service.Controllers CheckInTime = null, CheckInId = null, }; - } + } } else { @@ -522,41 +534,97 @@ namespace BMA.EHR.Leave.Service.Controllers var serializedObject = JsonConvert.SerializeObject(checkData); var body = Encoding.UTF8.GetBytes(serializedObject); + // add task id for check in queue + string taskId = Guid.NewGuid().ToString(); + var properties = channel.CreateBasicProperties(); + properties.Persistent = true; + properties.MessageId = taskId; // แนบ Message ID เพื่อใช้ตรวจสอบ + channel.BasicPublish(exchange: "", routingKey: queue, - basicProperties: null, + basicProperties: properties, body: body); - return Success(new { date = currentDate }); + return Success(new { date = currentDate, taskId = taskId }); } finally { _objectPool.Return(channel); } + } - //// create connection - //var factory = new ConnectionFactory() - //{ - // HostName = _configuration["Rabbit:Host"], - // UserName = _configuration["Rabbit:User"], - // Password = _configuration["Rabbit:Password"], - //}; + [HttpGet("check-status/{id:guid}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [AllowAnonymous] + public async Task> CheckInCheckStatus(Guid id) + { + var currentDate = DateTime.Now; + var channel = _objectPool.Get(); + try + { + var _url = _configuration["Rabbit:URL"] ?? ""; + var _queue = _configuration["Rabbit:Queue"] ?? "basic-queue"; - //// create channel - //using var connection = factory.CreateConnection(); - //using var channel = connection.CreateModel(); - //channel.QueueDeclare(queue: "checkin-queue", durable: false, exclusive: false, autoDelete: false, arguments: null); + // Step 1: ตรวจสอบจำนวน message ทั้งหมดในคิว + string queueUrl = $"{_url}{_queue}"; + var queueResponse = await _httpClient.GetAsync(queueUrl); + if (!queueResponse.IsSuccessStatusCode) + { + return Error("Error accessing RabbitMQ API", (int)queueResponse.StatusCode); + } - //// แปลง Object เป็น JSON สตริง - //var serializedObject = JsonConvert.SerializeObject(checkData); + var queueContent = await queueResponse.Content.ReadAsStringAsync(); + var queueData = JObject.Parse(queueContent); + int totalMessages = queueData["messages"]?.Value() ?? 0; - //// แปลง JSON สตริงเป็น byte array - //var body = Encoding.UTF8.GetBytes(serializedObject); + // Step 2: วนลูปดึง message ทีละ 100 งาน + int batchSize = 100; + var allMessages = new List(); + int processedMessages = 0; - //channel.BasicPublish(exchange: "", routingKey: "checkin-queue", basicProperties: null, body: body); - //Console.WriteLine($"Send to Queue: {serializedObject}"); + while (processedMessages < totalMessages) + { + var requestBody = new StringContent( + $"{{\"count\":{batchSize},\"requeue\":true,\"encoding\":\"auto\",\"ackmode\":\"ack_requeue_true\"}}", + Encoding.UTF8, + "application/json" + ); - //return Success(new { date = currentDate }); + string getMessagesUrl = $"{_url}{_queue}/get"; + var response = await _httpClient.PostAsync(getMessagesUrl, requestBody); + if (!response.IsSuccessStatusCode) + { + return StatusCode((int)response.StatusCode, "Error retrieving messages from RabbitMQ."); + } + + var content = await response.Content.ReadAsStringAsync(); + var messages = JArray.Parse(content); + + if (messages.Count == 0) + { + break; + } + + processedMessages += messages.Count; + allMessages.AddRange(messages.Select(m => m["properties"].ToString())); + } + + // Step 3: ค้นหา taskIds ที่อยู่ใน messages ทั้งหมด + var foundTasks = allMessages.FirstOrDefault(x => x.Contains(id.ToString("D"))); + + return Success(new { taskId = id, InQueue = foundTasks != null }); + + } + catch (Exception ex) + { + return Error(ex, ex.Message); + } + finally + { + _objectPool.Return(channel); + } } /// @@ -580,16 +648,95 @@ namespace BMA.EHR.Leave.Service.Controllers { channel.QueueDeclare(queue: _fakeCheckInQueue, durable: true, exclusive: false, autoDelete: false, arguments: null); + // Create Task ID + string taskId = Guid.NewGuid().ToString(); + var properties = channel.CreateBasicProperties(); + properties.Persistent = true; + properties.MessageId = taskId; // แนบ Message ID เพื่อใช้ตรวจสอบ + var serializedObject = JsonConvert.SerializeObject(data); var body = Encoding.UTF8.GetBytes(serializedObject); channel.BasicPublish(exchange: "", routingKey: _fakeCheckInQueue, - basicProperties: null, + basicProperties: properties, body: body); - return Success(new { date = currentDate }); + return Success(new { date = currentDate, taskId = taskId }); + } + finally + { + _objectPool.Return(channel); + } + } + + [HttpGet("fake-check-status/{id:guid}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [AllowAnonymous] + public async Task> FakeCheckInCheckStatus(Guid id) + { + var currentDate = DateTime.Now; + var channel = _objectPool.Get(); + try + { + var _url = _configuration["Rabbit:URL"] ?? ""; + + // Step 1: ตรวจสอบจำนวน message ทั้งหมดในคิว + string queueUrl = $"{_url}{_fakeCheckInQueue}"; + var queueResponse = await _httpClient.GetAsync(queueUrl); + if (!queueResponse.IsSuccessStatusCode) + { + return Error("Error accessing RabbitMQ API", (int)queueResponse.StatusCode); + } + + var queueContent = await queueResponse.Content.ReadAsStringAsync(); + var queueData = JObject.Parse(queueContent); + int totalMessages = queueData["messages"]?.Value() ?? 0; + + // Step 2: วนลูปดึง message ทีละ 100 งาน + int batchSize = 100; + var allMessages = new List(); + int processedMessages = 0; + + while (processedMessages < totalMessages) + { + var requestBody = new StringContent( + $"{{\"count\":{batchSize},\"requeue\":true,\"encoding\":\"auto\",\"ackmode\":\"ack_requeue_true\"}}", + Encoding.UTF8, + "application/json" + ); + + string getMessagesUrl = $"{_url}{_fakeCheckInQueue}/get"; + var response = await _httpClient.PostAsync(getMessagesUrl, requestBody); + if (!response.IsSuccessStatusCode) + { + return StatusCode((int)response.StatusCode, "Error retrieving messages from RabbitMQ."); + } + + var content = await response.Content.ReadAsStringAsync(); + var messages = JArray.Parse(content); + + if (messages.Count == 0) + { + break; + } + + processedMessages += messages.Count; + allMessages.AddRange(messages.Select(m => m["properties"].ToString())); + } + + // Step 3: ค้นหา taskIds ที่อยู่ใน messages ทั้งหมด + var foundTasks = allMessages.FirstOrDefault(x => x.Contains(id.ToString("D"))); + + return Success(new { taskId = id, InQueue = foundTasks != null }); + + } + catch (Exception ex) + { + return Error(ex, ex.Message); } finally { diff --git a/BMA.EHR.Leave/Program.cs b/BMA.EHR.Leave/Program.cs index 217aedaa..44bdd418 100644 --- a/BMA.EHR.Leave/Program.cs +++ b/BMA.EHR.Leave/Program.cs @@ -90,6 +90,8 @@ var builder = WebApplication.CreateBuilder(args); builder.Services.AddPersistence(builder.Configuration); builder.Services.AddLeavePersistence(builder.Configuration); + builder.Services.AddHttpClient(); + builder.Services.AddControllers(options => { options.SuppressAsyncSuffixInActionNames = false; diff --git a/BMA.EHR.Leave/appsettings.json b/BMA.EHR.Leave/appsettings.json index 7d2c53d1..662fd98f 100644 --- a/BMA.EHR.Leave/appsettings.json +++ b/BMA.EHR.Leave/appsettings.json @@ -45,7 +45,8 @@ "Host": "192.168.1.40", "User": "admin", "Password": "Test123456", - "Queue": "bma-checkin-queue" + "Queue": "bma-checkin-queue", + "URL": "https://edm-mq.frappet.synology.me/api/queues/%2F/" }, "Mail": { "Server": "mail.bangkok.go.th",