public bool SendLocationIsolationCrew(long outageId)
        {
            OutageEntity        outageEntity  = null;
            List <OutageEntity> activeOutages = null;
            long reportedGid = 0;
            bool result      = false;

            try
            {
                outageEntity = dbContext.OutageRepository.Get(outageId);
            }
            catch (Exception ex)
            {
                Logger.LogError($"OutageModel::SendLocationIsolationCrew => exception in UnitOfWork.OutageRepository.Get()", ex);
            }

            try
            {
                activeOutages = dbContext.OutageRepository.GetAllActive().ToList();
            }
            catch (Exception ex)
            {
                Logger.LogError("OutageModel::SendLocationIsolationCrew => excpetion in UnitOfWork.OutageRepository.GetAllActive()", ex);
                return(false);
            }
            if (outageEntity == null)
            {
                Logger.LogError($"Outage with id 0x{outageId:X16} is not found in database.");
                return(false);
            }

            reportedGid = outageEntity.DefaultIsolationPoints.First().EquipmentId;

            Task algorithm = Task.Run(() => StartLocationAndIsolationAlgorithm(outageEntity)).ContinueWith(task =>
            {
                result = task.Result;
                if (task.IsCompleted)
                {
                    dbContext.Complete();
                }
            }, TaskContinuationOptions.OnlyOnRanToCompletion).ContinueWith(task =>
            {
                outageModel.PublishOutage(Topic.ACTIVE_OUTAGE, outageMessageMapper.MapOutageEntity(outageEntity));
            }, TaskContinuationOptions.OnlyOnRanToCompletion);

            algorithm.Wait();

            return(result);
        }
コード例 #2
0
        public async Task <bool> SendLocationIsolationCrew(long outageId)
        {
            Logger.LogVerbose($"{baseLogString} SendLocationIsolationCrew method started. OutageId {outageId}");

            while (!ReliableDictionariesInitialized)
            {
                await Task.Delay(1000);
            }

            try
            {
                var result = await lifecycleHelper.GetCreatedOutage(outageId);

                if (!result.HasValue)
                {
                    Logger.LogError($"{baseLogString} SendLocationIsolationCrew => Created Outage is null. OutageId {outageId}");
                    return(false);
                }

                var outageEntity = result.Value;

                var enumerableTopology = await OutageTopologyModel.GetEnumerableDictionaryAsync();

                if (!enumerableTopology.ContainsKey(ReliableDictionaryNames.OutageTopologyModel))
                {
                    Logger.LogError($"{baseLogString} Start => Topology not found in Rel Dictionary: {ReliableDictionaryNames.OutageTopologyModel}.");
                    return(false);
                }

                var topology = enumerableTopology[ReliableDictionaryNames.OutageTopologyModel];

                if (!await StartLocationAndIsolationAlgorithm(outageEntity, topology))
                {
                    return(false);
                }

                return(await lifecycleHelper.PublishOutageAsync(Topic.ACTIVE_OUTAGE, outageMessageMapper.MapOutageEntity(outageEntity)));
            }
            catch (Exception e)
            {
                string message = $"{baseLogString} SendLocationIsolationCrew => Exception: {e.Message}";
                Logger.LogError(message, e);

                return(false);
            }
        }
コード例 #3
0
        public void IsolateOutage(long outageId)
        {
            //bool success = false;
            OutageEntity outageToIsolate = dbContext.OutageRepository.Get(outageId);

            if (outageToIsolate != null)
            {
                if (outageToIsolate.OutageState == OutageState.CREATED)
                {
                    Task.Run(() => StartIsolationAlgorthm(outageToIsolate))
                    .ContinueWith(task =>
                    {
                        if (task.Result)
                        {
                            dbContext.Complete();
                        }
                    }, TaskContinuationOptions.OnlyOnRanToCompletion)
                    .ContinueWith(task =>
                    {
                        try
                        {
                            outageModel.PublishOutage(Topic.ACTIVE_OUTAGE, outageMessageMapper.MapOutageEntity(outageToIsolate));
                            Logger.LogInfo($"Outage with id: 0x{outageToIsolate.OutageId:x16} is successfully published.");
                        }
                        catch (Exception e)
                        {
                            //TODO: mozda publish neke greske??
                            Logger.LogError("Error occured while trying to publish outage.", e);
                        }
                    }, TaskContinuationOptions.OnlyOnRanToCompletion);
                }
                else
                {
                    Logger.LogWarn($"Outage with id 0x{outageId:X16} is in state {outageToIsolate.OutageState}, and thus cannot be isolated.");
                }
            }
            else
            {
                Logger.LogWarn($"Outage with id 0x{outageId:X16} is not found in database.");
                //success = false;
            }

            //return success;
        }
        public async Task <bool> ResolveOutage(long outageId)
        {
            Logger.LogVerbose($"{baseLogString} ResolveOutage method started. OutageId: {outageId}");

            while (!ReliableDictionariesInitialized)
            {
                await Task.Delay(1000);
            }

            try
            {
                var result = await lifecycleHelper.GetValidatedRepairedOutage(outageId);

                if (!result.HasValue)
                {
                    Logger.LogError($"{baseLogString} ResolveOutage => GetValidatedRepairedOutage did not return a value. OutageId: {outageId}");
                    return(false);
                }

                var outageDbEntity = result.Value;
                outageDbEntity.ArchivedTime = DateTime.UtcNow;
                outageDbEntity.OutageState  = OutageState.ARCHIVED;

                var outageModelAccessClient = OutageModelAccessClient.CreateClient();
                await outageModelAccessClient.UpdateOutage(outageDbEntity);

                Logger.LogInformation($"{baseLogString} ResolveOutage => Outage on element with gid: 0x{outageDbEntity.OutageElementGid:x16} is SUCCESSFULLY archived.");

                return(await lifecycleHelper.PublishOutageAsync(Topic.ARCHIVED_OUTAGE, outageMessageMapper.MapOutageEntity(outageDbEntity)));
            }
            catch (Exception e)
            {
                string message = $"{baseLogString} ResolveOutage => Exception: {e.Message}";
                Logger.LogError(message, e);

                return(false);
            }
        }
コード例 #5
0
        public async Task <bool> ReportPotentialOutage(long elementGid, CommandOriginType commandOriginType, NetworkType networkType)
        {
            Logger.LogVerbose($"{baseLogString} ReportPotentialOutage method started. ElementGid: 0x{elementGid:X16}, CommandOriginType: {commandOriginType}, NetworkType: {networkType}");

            while (!ReliableDictionariesInitialized)
            {
                await Task.Delay(1000);
            }

            try
            {
                #region Preconditions
                var ceModelProviderClient = CeModelProviderClient.CreateClient();
                if (await ceModelProviderClient.IsRecloser(elementGid))
                {
                    Logger.LogWarning($"{baseLogString} ReportPotentialOutage => Element with gid 0x{elementGid:X16} is a Recloser. Call to ReportPotentialOutage aborted.");
                    return(false);
                }

                var enumerableTopology = await OutageTopologyModel.GetEnumerableDictionaryAsync();

                if (!enumerableTopology.ContainsKey(ReliableDictionaryNames.OutageTopologyModel))
                {
                    Logger.LogError($"{baseLogString} ReportPotentialOutage => Topology not found in Rel Dictionary: {ReliableDictionaryNames.OutageTopologyModel}.");
                    return(false);
                }

                var topology = enumerableTopology[ReliableDictionaryNames.OutageTopologyModel];
                var affectedConsumersGids = lifecycleHelper.GetAffectedConsumers(elementGid, topology, networkType);

                var historyDBManagerClient = HistoryDBManagerClient.CreateClient();

                if (!(await CheckPreconditions(elementGid, commandOriginType, affectedConsumersGids, historyDBManagerClient)))
                {
                    Logger.LogWarning($"{baseLogString} ReportPotentialOutage => Parameters do not satisfy required preconditions. ElementId: 0x{elementGid:X16}, CommandOriginType: {commandOriginType}");
                    return(false);
                }
                #endregion Preconditions

                Logger.LogInformation($"{baseLogString} ReportPotentialOutage => Reporting outage for gid: 0x{elementGid:X16}, CommandOriginType: {commandOriginType}");

                var result = await StoreActiveOutage(elementGid, affectedConsumersGids, topology);

                if (!result.HasValue)
                {
                    Logger.LogError($"{baseLogString} ReportPotentialOutage => Storing outage on element 0x{elementGid:X16} FAILED.");
                    return(false);
                }

                var createdOutage = result.Value;
                Logger.LogInformation($"{baseLogString} ReportPotentialOutage => Outage on element with gid: 0x{createdOutage.OutageElementGid:x16} is successfully stored in database.");

                //await historyDBManagerClient.OnSwitchOpened(elementGid, createdOutage.OutageId);
                //await historyDBManagerClient.OnConsumerBlackedOut(affectedConsumersGids, createdOutage.OutageId);

                return(await lifecycleHelper.PublishOutageAsync(Topic.ACTIVE_OUTAGE, outageMessageMapper.MapOutageEntity(createdOutage)));
            }
            catch (Exception e)
            {
                string message = $"{baseLogString} ReportPotentialOutage =>  exception: {e.Message}";
                Logger.LogError(message, e);
                return(false);
            }
        }
コード例 #6
0
        private async Task <bool> FinishIndividualAlgorithmCycle(IsolationAlgorithm algorithm, OutageTopologyModel topology)
        {
            var algorithmBaseLogString = $"{baseLogString} [HeadBreakerGid: 0x{algorithm.HeadBreakerGid:X16}]";

            Logger.LogInformation($"{algorithmBaseLogString} entering FinishIndividualAlgorithmCycle.");

            if (algorithm.CurrentBreakerGid <= 0 || algorithm.CurrentBreakerGid == algorithm.RecloserGid)
            {
                string message = $"{algorithmBaseLogString} FinishIndividualAlgorithmCycle => End of the feeder, no outage detected.";
                Logger.LogWarning(message);
                return(false);
            }

            var getCreatedOutageResult = await lifecycleHelper.GetCreatedOutage(algorithm.OutageId);

            if (!getCreatedOutageResult.HasValue)
            {
                Logger.LogError($"{algorithmBaseLogString} FinishIndividualAlgorithmCycle => Created Outage is null. OutageId: {algorithm.OutageId}");
                return(false);
            }

            var outageToIsolate = getCreatedOutageResult.Value;

            await SetDefaultIsolationPoints(outageToIsolate, algorithm);
            await SetOptimumIsolationPoints(outageToIsolate, algorithm, topology);

            //ISOLATE on optimum points
            var firstOptimumPoint  = outageToIsolate.OptimumIsolationPoints[0];
            var secondOptimumPoint = outageToIsolate.OptimumIsolationPoints[1];

            var commands = new Dictionary <long, DiscreteCommandingType>
            {
                { algorithm.HeadBreakerGid, DiscreteCommandingType.CLOSE },
                { firstOptimumPoint.EquipmentId, DiscreteCommandingType.OPEN },
                { secondOptimumPoint.EquipmentId, DiscreteCommandingType.OPEN },
                { algorithm.RecloserGid, DiscreteCommandingType.CLOSE },
            };

            var enumerableCommandedElements = await CommandedElements.GetEnumerableDictionaryAsync();

            if (!await SendCommands(algorithm, commands, enumerableCommandedElements))
            {
                string message = $"{algorithmBaseLogString} FinishIndividualAlgorithmCycle => Failed on SendMultipleScadaCommandAsync.";
                Logger.LogError(message);
                return(false);
            }

            long outageElementGid = topology.OutageTopology[secondOptimumPoint.EquipmentId].FirstEnd; //element iznad donjeg pointa - moze biti samo jedan gornji element (parent)

            if (!topology.OutageTopology[firstOptimumPoint.EquipmentId].SecondEnd.Contains(outageElementGid))
            {
                string message = $"{algorithmBaseLogString} FinishIndividualAlgorithmCycle => Outage element with gid: 0x{outageElementGid:X16} is not on a second end of current breaker id";
                Logger.LogError(message);
                return(false);
            }

            outageToIsolate.IsolatedTime     = DateTime.UtcNow;
            outageToIsolate.OutageElementGid = outageElementGid;
            outageToIsolate.OutageState      = OutageState.ISOLATED;

            var outageModelAccessClient = OutageModelAccessClient.CreateClient();
            await outageModelAccessClient.UpdateOutage(outageToIsolate);

            Logger.LogInformation($"{algorithmBaseLogString} FinishIndividualAlgorithmCycle => Isolation of outage with id: {outageToIsolate.OutageId}. Optimum isolation points: 0x{outageToIsolate.OptimumIsolationPoints[0].EquipmentId:X16} and 0x{outageToIsolate.OptimumIsolationPoints[1].EquipmentId:X16}, and outage element id is 0x{outageElementGid:X16}");

            await lifecycleHelper.PublishOutageAsync(Topic.ACTIVE_OUTAGE, outageMessageMapper.MapOutageEntity(outageToIsolate));

            Logger.LogInformation($"{algorithmBaseLogString} FinishIndividualAlgorithmCycle => Outage with id: 0x{outageToIsolate.OutageId:x16} is successfully published.");

            await OnEndAlgorithmCleanUp(algorithm.HeadBreakerGid);

            return(true);
        }
コード例 #7
0
        public bool ResolveOutage(long outageId)
        {
            OutageEntity activeOutageDbEntity = null;

            try
            {
                activeOutageDbEntity = dbContext.OutageRepository.Get(outageId);
            }
            catch (Exception e)
            {
                string message = "OutageModel::SendRepairCrew => exception in UnitOfWork.ActiveOutageRepository.Get()";
                Logger.LogError(message, e);
                throw e;
            }

            if (activeOutageDbEntity == null)
            {
                Logger.LogError($"Outage with id 0x{outageId:X16} is not found in database.");
                return(false);
            }

            if (activeOutageDbEntity.OutageState != OutageState.REPAIRED)
            {
                Logger.LogError($"Outage with id 0x{outageId:X16} is in state {activeOutageDbEntity.OutageState}, and thus repair crew can not be sent. (Expected state: {OutageState.REPAIRED})");
                return(false);
            }

            if (!activeOutageDbEntity.IsResolveConditionValidated)
            {
                //TODO: mozda i ovde odraditi proveru uslova?
                Logger.LogWarn("ResolveOutage => resolve conditions not validated.");
                return(false);
            }

            OutageEntity createdArchivedOutage = new OutageEntity()
            {
                OutageId                    = activeOutageDbEntity.OutageId,
                OutageState                 = OutageState.ARCHIVED,
                OutageElementGid            = activeOutageDbEntity.OutageElementGid,
                IsResolveConditionValidated = activeOutageDbEntity.IsResolveConditionValidated,
                ReportTime                  = activeOutageDbEntity.ReportTime,
                IsolatedTime                = activeOutageDbEntity.IsolatedTime,
                RepairedTime                = activeOutageDbEntity.RepairedTime,
                ArchivedTime                = DateTime.UtcNow,
                DefaultIsolationPoints      = new List <Equipment>(activeOutageDbEntity.DefaultIsolationPoints),
                OptimumIsolationPoints      = new List <Equipment>(activeOutageDbEntity.OptimumIsolationPoints),
                AffectedConsumers           = new List <Consumer>(activeOutageDbEntity.AffectedConsumers),
            };

            bool success;

            dbContext.OutageRepository.Remove(activeOutageDbEntity);
            OutageEntity archivedOutageDbEntity = dbContext.OutageRepository.Add(createdArchivedOutage);

            try
            {
                dbContext.Complete();
                Logger.LogDebug($"ArchivedOutage on element with gid: 0x{archivedOutageDbEntity.OutageElementGid:x16} is successfully stored in database.");
                success = true;
            }
            catch (Exception e)
            {
                string message = "OutageModel::ResolveOutage method => exception on Complete()";
                Logger.LogError(message, e);
                Console.WriteLine($"{message}, Message: {e.Message})");

                //TODO: da li je dobar handle?
                dbContext.Dispose();
                dbContext = new UnitOfWork();
                success   = false;
            }

            if (success && archivedOutageDbEntity != null) //TODO: ne svidja mi se ova konstrukcija...
            {
                try
                {
                    success = outageModel.PublishOutage(Topic.ARCHIVED_OUTAGE, outageMessageMapper.MapOutageEntity(archivedOutageDbEntity));

                    if (success)
                    {
                        Logger.LogInfo($"ArchivedOutage on element with gid: 0x{archivedOutageDbEntity.OutageElementGid:x16} is successfully published");
                    }
                }
                catch (Exception e) //TODO: Exception over proxy or enum...
                {
                    Logger.LogError("OutageModel::ResolveOutage => exception on PublishActiveOutage()", e);
                    success = false;
                }
            }

            return(success);
        }
コード例 #8
0
        public bool ValidateResolveConditions(long outageId)
        {
            OutageEntity outageDbEntity = null;

            try
            {
                outageDbEntity = dbContext.OutageRepository.Get(outageId);
            }
            catch (Exception e)
            {
                string message = "OutageModel::SendRepairCrew => exception in UnitOfWork.ActiveOutageRepository.Get()";
                Logger.LogError(message, e);
                throw e;
            }

            if (outageDbEntity == null)
            {
                Logger.LogError($"Outage with id 0x{outageId:X16} is not found in database.");
                return(false);
            }

            if (outageDbEntity.OutageState != OutageState.REPAIRED)
            {
                Logger.LogError($"Outage with id 0x{outageId:X16} is in state {outageDbEntity.OutageState}, and thus repair crew can not be sent. (Expected state: {OutageState.REPAIRED})");
                return(false);
            }

            List <Equipment> isolationPoints = new List <Equipment>();

            isolationPoints.AddRange(outageDbEntity.DefaultIsolationPoints);
            isolationPoints.AddRange(outageDbEntity.OptimumIsolationPoints);

            bool resolveCondition = true;

            foreach (Equipment isolationPoint in isolationPoints)
            {
                if (outageModel.TopologyModel.GetElementByGid(isolationPoint.EquipmentId, out IOutageTopologyElement element))
                {
                    if (element.NoReclosing != element.IsActive)
                    {
                        resolveCondition = false;
                        break;
                    }
                }
            }

            outageDbEntity.IsResolveConditionValidated = resolveCondition;

            dbContext.OutageRepository.Update(outageDbEntity);

            try
            {
                dbContext.Complete();
                outageModel.PublishOutage(Topic.ACTIVE_OUTAGE, outageMessageMapper.MapOutageEntity(outageDbEntity));
            }
            catch (Exception e)
            {
                string message = "OutageModel::ValidateResolveConditions => exception in Complete method.";
                Logger.LogError(message, e);
            }

            return(true);
        }
コード例 #9
0
        public bool SendRepairCrew(long outageId)
        {
            OutageEntity outageDbEntity = null;

            try
            {
                outageDbEntity = dbContext.OutageRepository.Get(outageId);
            }
            catch (Exception e)
            {
                string message = "OutageModel::SendRepairCrew => exception in UnitOfWork.ActiveOutageRepository.Get()";
                Logger.LogError(message, e);
                throw e;
            }

            if (outageDbEntity == null)
            {
                Logger.LogError($"Outage with id 0x{outageId:X16} is not found in database.");
                return(false);
            }

            if (outageDbEntity.OutageState != OutageState.ISOLATED)
            {
                Logger.LogError($"Outage with id 0x{outageId:X16} is in state {outageDbEntity.OutageState}, and thus repair crew can not be sent. (Expected state: {OutageState.ISOLATED})");
                return(false);
            }

            Task task = Task.Run(() =>
            {
                Task.Delay(10000).Wait();

                using (OutageSimulatorServiceProxy proxy = proxyFactory.CreateProxy <OutageSimulatorServiceProxy, IOutageSimulatorContract>(EndpointNames.OutageSimulatorServiceEndpoint))
                {
                    if (proxy == null)
                    {
                        string message = "OutageModel::SendRepairCrew => OutageSimulatorServiceProxy is null";
                        Logger.LogError(message);
                        throw new NullReferenceException(message);
                    }

                    if (proxy.StopOutageSimulation(outageDbEntity.OutageElementGid))
                    {
                        outageDbEntity.OutageState  = OutageState.REPAIRED;
                        outageDbEntity.RepairedTime = DateTime.UtcNow;
                        dbContext.OutageRepository.Update(outageDbEntity);

                        try
                        {
                            dbContext.Complete();
                            outageModel.PublishOutage(Topic.ACTIVE_OUTAGE, outageMessageMapper.MapOutageEntity(outageDbEntity));
                        }
                        catch (Exception e)
                        {
                            string message = "OutageModel::SendRepairCrew => exception in Complete method.";
                            Logger.LogError(message, e);
                        }
                    }
                    else
                    {
                        string message = "OutageModel::SendRepairCrew => ResolvedOutage() not finished with SUCCESS";
                        Logger.LogError(message);
                    }
                }
            });

            return(true);
        }
コード例 #10
0
        public bool ReportPotentialOutage(long gid, CommandOriginType commandOriginType)
        {
            bool        success = false;
            List <long> affectedConsumersIds = new List <long>();

            affectedConsumersIds = GetAffectedConsumers(gid);

            if (commandOriginType != CommandOriginType.USER_COMMAND &&
                commandOriginType != CommandOriginType.ISOLATING_ALGORITHM_COMMAND)
            {
                Logger.LogDebug($"Reporting outage for gid: 0x{gid:X16}");

                if (outageModel.commandedElements.Contains(gid) || outageModel.optimumIsolationPoints.Contains(gid))
                {
                    outageModel.SwitchOpened?.Invoke(gid, null);
                    outageModel.ConsumersBlackedOut?.Invoke(affectedConsumersIds, null);
                    return(false);
                }

                if (affectedConsumersIds.Count == 0)
                {
                    bool isSwitchInvoked = false;
                    if (recloserOutageMap.TryGetValue(gid, out Dictionary <long, List <long> > outageAffectedPair))
                    {
                        foreach (var pair in outageAffectedPair)
                        {
                            outageModel.ConsumersBlackedOut?.Invoke(pair.Value, pair.Key);
                            outageModel.SwitchOpened?.Invoke(gid, pair.Key);
                            isSwitchInvoked = true;
                        }
                    }

                    if (!isSwitchInvoked)
                    {
                        outageModel.SwitchOpened?.Invoke(gid, null);
                    }

                    Logger.LogInfo("There is no affected consumers => outage report is not valid.");
                    return(false);
                }

                OutageEntity activeOutageDbEntity = null;

                if (dbContext.OutageRepository.Find(o => o.OutageElementGid == gid && o.OutageState != OutageState.ARCHIVED).FirstOrDefault() != null)
                {
                    Logger.LogWarn($"Malfunction on element with gid: 0x{gid:x16} has already been reported.");
                    return(false);
                }

                List <Consumer> consumerDbEntities = outageModel.GetAffectedConsumersFromDatabase(affectedConsumersIds);

                if (consumerDbEntities.Count != affectedConsumersIds.Count)
                {
                    Logger.LogWarn("Some of affected consumers are not present in database");
                    return(false);
                }

                long recloserId;

                try
                {
                    recloserId = outageModel.GetRecloserForHeadBreaker(gid);
                }
                catch (Exception)
                {
                    return(false);
                }

                List <Equipment> defaultIsolationPoints = outageModel.GetEquipmentEntity(new List <long> {
                    gid, recloserId
                });

                OutageEntity createdActiveOutage = new OutageEntity
                {
                    AffectedConsumers      = consumerDbEntities,
                    OutageState            = OutageState.CREATED,
                    ReportTime             = DateTime.UtcNow,
                    DefaultIsolationPoints = defaultIsolationPoints,
                };

                activeOutageDbEntity = dbContext.OutageRepository.Add(createdActiveOutage);

                try
                {
                    dbContext.Complete();
                    Logger.LogDebug($"Outage on element with gid: 0x{activeOutageDbEntity.OutageElementGid:x16} is successfully stored in database.");
                    success = true;

                    if (recloserOutageMap.TryGetValue(recloserId, out Dictionary <long, List <long> > outageAffectedPair))
                    {
                        if (outageAffectedPair.TryGetValue(createdActiveOutage.OutageId, out List <long> affected))
                        {
                            affected = new List <long>(affectedConsumersIds);
                        }
                        else
                        {
                            outageAffectedPair.Add(createdActiveOutage.OutageId, affectedConsumersIds);
                        }
                    }
                    else
                    {
                        Dictionary <long, List <long> > dict = new Dictionary <long, List <long> >()
                        {
                            { createdActiveOutage.OutageId, affectedConsumersIds }
                        };

                        recloserOutageMap.Add(recloserId, dict);
                    }

                    outageModel.SwitchOpened?.Invoke(gid, createdActiveOutage.OutageId);
                    outageModel.ConsumersBlackedOut?.Invoke(affectedConsumersIds, createdActiveOutage.OutageId);
                }
                catch (Exception e)
                {
                    string message = "OutageModel::ReportPotentialOutage method => exception on Complete()";
                    Logger.LogError(message, e);
                    Console.WriteLine($"{message}, Message: {e.Message}, Inner Message: {e.InnerException.Message})");

                    //TODO: da li je dobar handle?
                    dbContext.Dispose();
                    dbContext = new UnitOfWork();
                    success   = false;
                }

                if (success && activeOutageDbEntity != null)
                {
                    try
                    {
                        success = outageModel.PublishOutage(Topic.ACTIVE_OUTAGE, outageMessageMapper.MapOutageEntity(activeOutageDbEntity));

                        if (success)
                        {
                            Logger.LogInfo($"Outage on element with gid: 0x{activeOutageDbEntity.OutageElementGid:x16} is successfully published");
                        }
                    }
                    catch (Exception e) //TODO: Exception over proxy or enum...
                    {
                        Logger.LogError("OutageModel::ReportPotentialOutage => exception on PublishActiveOutage()", e);
                        success = false;
                    }
                }
            }
            else
            {
                //USER COMANDA - korisnik rucno otvara neki breaker -> nije outage ali korisnici potencijalno ostaju bez napajanja
                outageModel.SwitchOpened?.Invoke(gid, null);
                outageModel.ConsumersBlackedOut?.Invoke(affectedConsumersIds, null);
            }

            return(success);
        }