using System; using MySql.Data.MySqlClient; using FellowOakDicom; using FellowOakDicom.Network; using FellowOakDicom.Network.Client; using Microsoft.Extensions.Configuration; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.Extensions.DependencyInjection; using System.Threading; namespace DicomMigratorApp { class Program { private static IConfiguration Configuration; private static ILogger _logger; private static string connectionString; private static string targetIP; private static string senderAET; private static string targetAET; private static int targetPort; private static string db_status_to_pick; static async Task Main(string[] args) { var serviceProvider = new ServiceCollection() .AddLogging(config => { config.AddConsole(); config.SetMinimumLevel(LogLevel.Information); }) .BuildServiceProvider(); _logger = serviceProvider.GetService() .CreateLogger(); _logger.LogInformation("Application started"); connectionString = Environment.GetEnvironmentVariable("ConnectionStrings__DefaultConnection") ?? "Server=127.0.0.1;Port=3306;Database=dms_db;User Id=root;Password=Rootmatrix23@;"; targetIP = Environment.GetEnvironmentVariable("Dest__IP") ?? "127.0.0.1"; senderAET = Environment.GetEnvironmentVariable("Sender__AET") ?? "MYAE"; targetAET = Environment.GetEnvironmentVariable("Dest__AET") ?? "ORTHANC"; var targetPortStr = Environment.GetEnvironmentVariable("Dest__Port") ?? "4242"; db_status_to_pick = Environment.GetEnvironmentVariable("DB_STATUS") ?? "MIGRATION_QUEUE"; if (!int.TryParse(targetPortStr, out targetPort)) { _logger.LogError("TargetServer__Port environment variable is not a valid integer."); return; } while (true) { try { var imagePaths = await GetMigrationImages(connectionString,db_status_to_pick); if (imagePaths == null || imagePaths.Count == 0) { await Task.Delay(5000); continue; } foreach (var image in imagePaths) { try { await MigrateImage(image.Path); await UpdateImagePathStatus(connectionString, image.Id, "MIGRATION_COMPLETE"); } catch (DicomAssociationRejectedException ex) { _logger.LogError(ex, $"Association rejected for image path {image.Path}"); await UpdateImagePathStatus(connectionString, image.Id, "MIGRATION_ERRORED"); } catch (Exception ex) { _logger.LogError(ex, $"An error occurred while migrating image path {image.Path}"); await UpdateImagePathStatus(connectionString, image.Id, "MIGRATION_ERRORED"); } } } catch (MySqlException ex) { _logger.LogError(ex, "An error occurred while connecting to the database"); break; } catch (Exception ex) { _logger.LogError(ex, "An error occurred in the main processing loop"); break; } } } private static async Task> GetMigrationImages(string connectionString, string db_status_to_pick) { var imagePaths = new List(); try { using (var connection = new MySqlConnection(connectionString)) { await connection.OpenAsync(); _logger.LogInformation("Database connection established"); var command = new MySqlCommand("SELECT id, image_path FROM priority_migration_image WHERE status=@Status order by priority LIMIT 10", connection); command.Parameters.AddWithValue("@Status", db_status_to_pick); var reader = await command.ExecuteReaderAsync(); while (await reader.ReadAsync()) { imagePaths.Add(new ImageRecord { Id = reader.IsDBNull(0) ? 0 : reader.GetInt32(0), Path = reader.IsDBNull(1) ? null : reader.GetString(1) }); } reader.Close(); } _logger.LogInformation($"Retrieved {imagePaths.Count} image paths for migration"); } catch (Exception ex) { _logger.LogError(ex, "Error retrieving image paths from the database"); throw; // Re-throw the exception to ensure it is caught by the outer try-catch block } return imagePaths; } private static async Task UpdateImagePathStatus(string connectionString, int imageId, string updateStatus) { try { using (var connection = new MySqlConnection(connectionString)) { await connection.OpenAsync(); var command = new MySqlCommand("UPDATE priority_migration_image SET status = @Status WHERE id = @ImageId", connection); command.Parameters.AddWithValue("@ImageId", imageId); command.Parameters.AddWithValue("@Status", updateStatus); await command.ExecuteNonQueryAsync(); _logger.LogInformation($"Updated image path record for image ID {imageId} with status {updateStatus}"); } } catch (Exception ex) { _logger.LogError(ex, $"Error updating image path record for image ID {imageId}"); throw; // Re-throw the exception to ensure it is caught by the outer try-catch block } } private static async Task MigrateImage(string imagePath) { try { var client = DicomClientFactory.Create(targetIP, targetPort, false, senderAET, targetAET); var dicomFile = await DicomFile.OpenAsync(imagePath); await client.AddRequestAsync(new DicomCStoreRequest(dicomFile)); await client.SendAsync(); _logger.LogInformation($"Migrated image {imagePath} to target AET {targetAET}"); } catch (Exception ex) { _logger.LogError(ex, $"Error migrating image {imagePath}"); throw; // Re-throw the exception to ensure it is caught by the outer try-catch block } } } class ImageRecord { public int Id { get; set; } public string Path { get; set; } } }