using FrameworkDAL.CustomCode.DataSync; using FrameworkDAL.DTO.DataSync; using GB5Shared.DaprCache; using GB5Shared.DTO.Framework.Login; using GB5Shared.EventLogPublish; using GB5Shared.GenerateAutoNumber; using GB5Shared.Resource.Response; using GB5Shared.ResponseStandard; using GB5Shared.Telemetry; using GB5Shared.Validation; using Microsoft.Extensions.Logging; using static GB5Shared.GB5Constant.Constant; namespace FrameworkBLL.DataSync { public class DataSyncJobBLL : IDataSyncJobBLL { private readonly IDataSyncJobDAL _dal; private readonly AutoNumber _autoNumber; private readonly IValidation _validation; private readonly EventLogPublish _eventLog; private readonly KeyInvalidate _keyInvalidate; private readonly ILogger _logger; public DataSyncJobBLL( IDataSyncJobDAL dal, AutoNumber autoNumber, IValidation validation, EventLogPublish eventLog, KeyInvalidate keyInvalidate, ILogger logger) { _dal = dal; _autoNumber = autoNumber; _validation = validation; _eventLog = eventLog; _keyInvalidate = keyInvalidate; _logger = logger; } // ── Read ────────────────────────────────────────────────────────────── public async Task GetSyncJob(int syncJobId, LoginDTO login, CancellationToken ct) { try { return await _dal.GetSyncJob(syncJobId, login, ct).ConfigureAwait(false); } catch (Exception ex) { GB5Trace.MarkFailed("get-syncjob-failed", ex); _logger.LogError(ex, "GetSyncJob failed for SyncJobId {SyncJobId}", syncJobId); throw; } } public async Task GetSyncJobList(int offset, int pageSize, LoginDTO login, CancellationToken ct) { try { return await _dal.GetSyncJobList(offset, pageSize, login, ct).ConfigureAwait(false); } catch (Exception ex) { GB5Trace.MarkFailed("get-syncjob-list-failed", ex); _logger.LogError(ex, "GetSyncJobList failed"); throw; } } public async Task GetSelectListSyncJob(int firstNumber, int maxResult, LoginDTO login, CancellationToken ct) { try { return await _dal.GetSelectListSyncJob(firstNumber, maxResult, login, ct).ConfigureAwait(false); } catch (Exception ex) { GB5Trace.MarkFailed("get-selectlist-syncjob-failed", ex); _logger.LogError(ex, "GetSelectListSyncJob failed"); throw; } } // ── Save (create + update) ──────────────────────────────────────────── public async Task SaveSyncJob(SyncJobDTO dto, LoginDTO login, CancellationToken ct) { if (dto is null) throw new ArgumentNullException(nameof(dto)); GB5Trace.Step("validate-syncjob", new { dto.SyncJobId }); await _validation.NotEmpty(dto.Description, nameof(dto.Description)); if (dto.SourceDBInstanceId <= 0) throw new ArgumentException("SourceDBInstanceId is required."); if (dto.TargetDBInstanceId <= 0) throw new ArgumentException("TargetDBInstanceId is required."); if (dto.DatasetId <= 0) throw new ArgumentException("DatasetId is required."); var isNew = dto.SyncJobId == 0; GB5Trace.Step("save-syncjob", new { dto.SyncJobId, isNew }); int savedId; if (isNew) { var autoNum = await _autoNumber.GetAutoNumber(1, AUTONUMBERCONSTANT.DSYNCJOB, login); dto.SyncJobId = autoNum.StartNumber; dto.Status = dto.Status == 0 ? (byte)1 : dto.Status; // 1=Active dto.IsEnabled = dto.IsEnabled == 0 ? (byte)1 : dto.IsEnabled; // default enabled dto.SortOrder = dto.SortOrder == 0 ? (short)9999 : dto.SortOrder; dto.SourceType = dto.SourceType == 0 ? (byte)5 : dto.SourceType; dto.Version = 0; dto.CreatedById = login.UserId; dto.CreatedOn = DateTime.UtcNow; dto.ModifiedById = login.UserId; dto.ModifiedOn = DateTime.UtcNow; savedId = await _dal.SaveSyncJob(dto, login, ct).ConfigureAwait(false); } else { dto.ModifiedById = login.UserId; dto.ModifiedOn = DateTime.UtcNow; dto.Version = (short)(dto.Version + 1); savedId = await _dal.UpdateSyncJob(dto, login, ct).ConfigureAwait(false); } var cacheKey = new CacheKeyGeneration().KeyGeneration( savedId, EntityConstant.OBJECTDSYNCJOB, CacheKeyLevel.CLIENT_LEVEL, login); await _keyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); var eventTypeId = isNew ? EventTypeConstant.SAVEDSYNCJOBEVENTTYPEID : EventTypeConstant.UPDATEDSYNCJOBEVENTTYPEID; GB5Trace.Step("event-publish", new { eventTypeId }); await _eventLog.PublishEventLogAsync( isNew ? $"DataSync Job Created: {dto.Description}" : $"DataSync Job Updated: {dto.Description}", dto, eventTypeId, dto.SyncJobId, login, "eventlog-topic" ).ConfigureAwait(false); return isNew ? $"{SuccessResponse.SaveSuccessMessage} {savedId}" : $"{SuccessResponse.UpdateSuccessMessage} {savedId}"; } // ── Delete ──────────────────────────────────────────────────────────── public async Task> DeleteSyncJob(int syncJobId, LoginDTO login, CancellationToken ct) { GB5Trace.Step("delete-syncjob", new { syncJobId }); try { var result = await _dal.DeleteSyncJob(syncJobId, login, ct).ConfigureAwait(false); if (result.IsSuccess) { var cacheKey = new CacheKeyGeneration().KeyGeneration( syncJobId, EntityConstant.OBJECTDSYNCJOB, CacheKeyLevel.CLIENT_LEVEL, login); await _keyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); GB5Trace.Step("event-publish", new { EventTypeConstant.DELETEDSYNCJOBEVENTTYPEID }); await _eventLog.PublishEventLogAsync( $"DataSync Job Deleted: SyncJobId={syncJobId}", new { SyncJobId = syncJobId }, EventTypeConstant.DELETEDSYNCJOBEVENTTYPEID, syncJobId, login, "eventlog-topic" ).ConfigureAwait(false); } return result; } catch (Exception ex) { GB5Trace.MarkFailed("delete-syncjob-failed", ex); _logger.LogError(ex, "DeleteSyncJob failed for SyncJobId {SyncJobId}", syncJobId); throw; } } } }