| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
- using Application.Abstractions.Cache;
- using Application.Abstractions.Data;
- using Infrastructure.Cache;
- using Infrastructure.Messaging.Email;
- using Infrastructure.Persistence;
- using MailWorker;
- using Serilog;
- using Serilog.Events;
- using SharedKernel;
- using StackExchange.Redis;
- using Microsoft.EntityFrameworkCore;
- using Microsoft.Extensions.Configuration;
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.Extensions.Hosting;
- using Microsoft.Extensions.Hosting.WindowsServices;
- using Microsoft.Extensions.Logging;
- using Microsoft.AspNetCore.DataProtection;
- var builder = Host.CreateApplicationBuilder(args);
- var settings = builder.Configuration.Get<AppSettings>()!;
- if (!WindowsServiceHelpers.IsWindowsService())
- {
- Console.Title = "ANTOOZA MailWorker";
- }
- Console.WriteLine($"ENV={builder.Environment.EnvironmentName}");
- Console.WriteLine($"현재 시간: {DateTime.Now} / {TimeZoneInfo.Local.Id}");
- builder.Services.AddWindowsService();
- if (builder.Environment.IsProduction())
- {
- Log.Logger = new LoggerConfiguration()
- .MinimumLevel.Information()
- .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
- .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning)
- .WriteTo.Console()
- .WriteTo.File("logs/mailworker-.log",
- rollingInterval: RollingInterval.Day,
- retainedFileCountLimit: 30,
- outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {Message:lj}{NewLine}{Exception}")
- .CreateLogger();
- builder.Logging.ClearProviders();
- builder.Logging.AddSerilog(Log.Logger);
- }
- builder.Services.Configure<AppSettings>(builder.Configuration);
- // DB
- var dbConn = builder.Configuration.GetConnectionString("DefaultConnection");
- if (string.IsNullOrWhiteSpace(dbConn))
- {
- throw new InvalidOperationException("Connection string 'DefaultConnection' is not configured.");
- }
- builder.Services.AddDbContext<AppDbContext>(options => options
- .UseSqlServer(dbConn)
- .ConfigureWarnings(w => w.Ignore(Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId.PendingModelChangesWarning)));
- builder.Services.AddScoped<IAppDbContext>(sp => sp.GetRequiredService<AppDbContext>());
- // Redis (Config 캐시 공유)
- var redis = ConnectionMultiplexer.Connect(settings.Redis.DefaultConnection);
- builder.Services.AddSingleton<IConnectionMultiplexer>(redis);
- builder.Services.AddDataProtection()
- .SetApplicationName(settings.App.Name)
- .PersistKeysToStackExchangeRedis(redis, settings.Redis.DataProtectionKey)
- .ProtectKeysWithDpapi(protectToLocalMachine: true) // key를 암호화하여 저장 (로컬 머신에서만 복호화 가능, 서버간 공유 불가)
- .SetDefaultKeyLifetime(settings.Redis.DefaultKeyLifetime); // 기본 90일 주기
- builder.Services.AddStackExchangeRedisCache(options =>
- {
- options.Configuration = settings.Redis.DefaultConnection;
- options.InstanceName = settings.Redis.CachePrefix;
- });
- builder.Services.AddSingleton<ICacheService, RedisCacheService>();
- // SMTP 직발 (Worker는 항상 Direct)
- builder.Services.AddScoped<DirectMailService>();
- // Hosted services
- builder.Services.AddHostedService<MailQueueWorker>();
- builder.Services.AddHostedService<EmailLogJanitor>();
- builder.Build().Run();
|