Esempio n. 1
0
        public bool Start()
        {
            PrintAction?.Invoke("BMemoryPubSubServiceTest->Info-> Test is starting.");

            if (SelectedMemoryService == null)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->Error-> Given SelectedMemoryService is null.");
                return(false);
            }

            if (!SelectedMemoryService.HasInitializationSucceed())
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->Error-> Initialization failed.");
                return(false);
            }

            if (SelectedMemoryService.GetPubSubService() == null)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->Error-> Given PubSubService is null.");
                return(false);
            }

            SelectedMemoryService.GetPubSubService().EnsureUniqueMessageDelivery(SelectedMemoryService, PrintAction);

            PrintAction?.Invoke("BMemoryPubSubServiceTest->Log-> Initialization succeed.");

            PreCleanup();

            SelectedMemoryService.GetPubSubService().Subscribe(
                MemoryQueryParameters,
                (string Topic, JObject Message) =>
            {
                lock (SubscribeDoneCounter.Monitor)
                {
                    SubscribeMessages.Add("BMemoryPubSubServiceTest->Sub-> " + Topic + "-> " + Message.ToString());
                    SubscribeDoneCounter.Set(SubscribeDoneCounter.Get() + 1);
                }
            },
                (string Message) =>
            {
                Console.WriteLine("BMemoryPubSubServiceTest->Sub->Error-> " + Message);
                FailureStatus.Set(true);
            });

            bool bLocalResult = SelectedMemoryService.SetKeyValue(
                MemoryQueryParameters,
                new Tuple <string, BPrimitiveType>[]
            {
                new Tuple <string, BPrimitiveType>("TestKey1", new BPrimitiveType(123)),
                new Tuple <string, BPrimitiveType>("TestKey2", new BPrimitiveType(123.00400422f)),
                new Tuple <string, BPrimitiveType>("TestKey3", new BPrimitiveType("TestVal3"))
            },
                (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->SetKeyValue-1->Error-> " + Message);
            });

            if (!bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->SetKeyValue-1 has failed.");
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->SetKeyValue-1 has succeed.");

            var LocalResult_1 = SelectedMemoryService.GetAllKeyValues(
                MemoryQueryParameters,
                (string Message) => Console.WriteLine("BMemoryPubSubServiceTest->GetAllKeyValues->Error-> " + Message));

            if (LocalResult_1 == null || LocalResult_1.Length != 3)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->GetAllKeyValues-1 has failed. IsNull: " + (LocalResult_1 == null) + ", Length: " + LocalResult_1?.Length);
                return(false);
            }
            foreach (var Tuple_1 in LocalResult_1)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->GetAllKeyValues-1->" + Tuple_1.Item1 + ": " + Tuple_1.Item2.ToString());
            }

            bLocalResult = SelectedMemoryService.DeleteAllKeys(
                MemoryQueryParameters,
                true,
                (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->DeleteAllKeys-1->Error-> " + Message);
            });
            if (!bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->DeleteAllKeys-1 has failed.");
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->DeleteAllKeys-1 has succeed.");

            bLocalResult = SelectedMemoryService.SetKeyValue(
                MemoryQueryParameters,
                new Tuple <string, BPrimitiveType>[]
            {
                new Tuple <string, BPrimitiveType>("TestKey1", new BPrimitiveType(123)),
                new Tuple <string, BPrimitiveType>("TestKey2", new BPrimitiveType(123.00400422f)),
                new Tuple <string, BPrimitiveType>("TestKey3", new BPrimitiveType("TestVal3"))
            },
                (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->SetKeyValue-2->Error-> " + Message);
            });
            if (!bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->SetKeyValue-2 has failed.");
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->SetKeyValue-2 has succeed.");

            bLocalResult = true;
            long KeysCount = SelectedMemoryService.GetKeysCount(
                MemoryQueryParameters,
                (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->GetKeysCount-1->Error-> " + Message);
            });

            if (!bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeysCount-1 has failed.");
                return(false);
            }
            if (KeysCount != 3)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeysCount-1 expected 3, but result is: " + KeysCount);
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeysCount-1 has succeed.");

            bLocalResult = true;
            SelectedMemoryService.IncrementKeyValues(
                MemoryQueryParameters,
                new Tuple <string, long>[]
            {
                new Tuple <string, long>("TestKey1", 100)
            },
                (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->IncrementKeyValues-1->Error-> " + Message);
            });
            if (!bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->IncrementKeyValues-1 has failed.");
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->IncrementKeyValues-1 has succeed.");

            bLocalResult = true;
            var Expected1223 = SelectedMemoryService.IncrementKeyByValueAndGet(MemoryQueryParameters,
                                                                               new Tuple <string, long>("TestKey1", 1000),
                                                                               (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->IncrementKeyByValueAndGet-1->Error-> " + Message);
            });

            if (!bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->IncrementKeyByValueAndGet-1 has failed.");
                return(false);
            }
            if (Expected1223 != 1223)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->IncrementKeyByValueAndGet-1 expected 1223, but result is: " + Expected1223);
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->IncrementKeyByValueAndGet-1 has succeed.");

            bLocalResult = SelectedMemoryService.PushToListHead(MemoryQueryParameters, "TestList1", new BPrimitiveType[]
            {
                new BPrimitiveType(123),
                new BPrimitiveType(234)
            },
                                                                false,
                                                                (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->PushToListHead-1->Error-> " + Message);
            });
            if (!bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->PushToListHead-1 has failed.");
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->PushToListHead-1 has succeed.");

            bLocalResult = SelectedMemoryService.PushToListTail(MemoryQueryParameters, "TestList1", new BPrimitiveType[]
            {
                new BPrimitiveType(345),
                new BPrimitiveType(456)
            },
                                                                true,
                                                                (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->PushToListTail-1->Error-> " + Message);
            });
            if (!bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->PushToListTail-1 has failed.");
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->PushToListTail-1 has succeed.");

            bLocalResult = true;
            var GetAllElementsOfListResult_1 = SelectedMemoryService.GetAllElementsOfList(MemoryQueryParameters, "TestList1",
                                                                                          (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->GetAllElementsOfList-1->Error-> " + Message);
            });

            if (!bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->GetAllElementsOfList-1 has failed.");
                return(false);
            }
            if (GetAllElementsOfListResult_1 == null || GetAllElementsOfListResult_1.Length != 4)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->GetAllElementsOfList-1 result is either null or length is unexpected. Length: " + GetAllElementsOfListResult_1?.Length);
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->GetAllElementsOfList-1 has succeed.");

            var PopFirstElementOfListResult_1 = SelectedMemoryService.PopFirstElementOfList(MemoryQueryParameters, "TestList1",
                                                                                            (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->PopFirstElementOfList-1->Error-> " + Message);
            });

            if (!bLocalResult || PopFirstElementOfListResult_1 == null)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->PopFirstElementOfList-1 has failed. PopFirstElementOfListResult_1 null status: " + (PopFirstElementOfListResult_1 == null));
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->PopFirstElementOfList-1 succeed. Result: " + PopFirstElementOfListResult_1.ToString());

            var PopLastElementOfListResult_1 = SelectedMemoryService.PopLastElementOfList(MemoryQueryParameters, "TestList1",
                                                                                          (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->PopLastElementOfList-1->Error-> " + Message);
            });

            if (!bLocalResult || PopLastElementOfListResult_1 == null)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->PopLastElementOfList-1 has failed. PopLastElementOfList_1 null status: " + (PopLastElementOfListResult_1 == null));
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->PopLastElementOfList-1 succeed. Result: " + PopLastElementOfListResult_1.ToString());

            bLocalResult = true;
            var ListSizeResult_1 = SelectedMemoryService.ListSize(MemoryQueryParameters, "TestList1",
                                                                  (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->ListSize-1->Error-> " + Message);
            });

            if (!bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->ListSize-1 has failed.");
                return(false);
            }
            if (ListSizeResult_1 != 2)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->ListSize-1: Expected result is 2, but returned: " + ListSizeResult_1);
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->ListSize-1 has succeed.");

            bLocalResult = SelectedMemoryService.ListContains(MemoryQueryParameters, "TestList1", new BPrimitiveType(123),
                                                              (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->ListContains-1->Error-> " + Message);
            });
            if (!bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->ListContains-1 has failed.");
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->ListContains-1 has succeed.");

            bLocalResult = SelectedMemoryService.EmptyList(MemoryQueryParameters, "TestList1", true,
                                                           (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->EmptyList-1->Error-> " + Message);
            });
            if (!bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->EmptyList-1 has failed.");
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->EmptyList-1 has succeed.");

            bLocalResult = true;
            var ListSizeResult_2 = SelectedMemoryService.ListSize(MemoryQueryParameters, "TestList1",
                                                                  (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->ListSize-2->Error-> " + Message);
            });

            if (!bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->ListSize-2 has failed.");
                return(false);
            }
            if (ListSizeResult_2 != 0)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->ListSize-2: Expected result is 0, but returned: " + ListSizeResult_1);
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->ListSize-2 has succeed.");

            bLocalResult = true;
            var Expected1223Value = SelectedMemoryService.GetKeyValue(
                MemoryQueryParameters,
                "TestKey1",
                (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->GetKeyValue-1->Error-> " + Message);
            });

            if (!bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeyValue-1 has failed.");
                return(false);
            }
            if (Expected1223Value == null || Expected1223Value.Type != EBPrimitiveTypeEnum.Integer || Expected1223Value.AsInteger != 1223)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeyValue-1 expected 1223, but result is: " + Expected1223Value?.ToString());
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeyValue-1 has succeed.");

            bLocalResult = SelectedMemoryService.DeleteKey(
                MemoryQueryParameters,
                "TestKey3",
                (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->DeleteKey-1->Error-> " + Message);
            });
            if (!bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->DeleteKey-1 has failed.");
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->DeleteKey-1 has succeed.");

            bLocalResult = SelectedMemoryService.DeleteKey(
                MemoryQueryParameters,
                "TestKeyNonExistent",
                (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->DeleteKey-2->Error-> Expected: " + Message);
            });
            if (bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->DeleteKey-2 did not fail.");
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->DeleteKey-2 has successfully failed.");

            bLocalResult = true;
            KeysCount    = SelectedMemoryService.GetKeysCount(
                MemoryQueryParameters,
                (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->GetKeysCount-2->Error-> " + Message);
            });
            if (!bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeysCount-2 has failed.");
                return(false);
            }
            if (KeysCount != 2)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeysCount-2 expected 2, but result is: " + KeysCount);
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeysCount-2 has succeed.");

            bLocalResult = true;
            var GetKeysResult = SelectedMemoryService.GetKeys(MemoryQueryParameters,
                                                              (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->GetKeys-1->Error-> " + Message);
            });

            if (!bLocalResult || GetKeysResult == null || GetKeysResult.Length != 2)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeys-1 returned " + GetKeysResult?.Length + " results, but expected 2. Error status: " + bLocalResult);
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeys-1 has succeed.");

            bLocalResult = true;
            var GetKeysValuesResult = SelectedMemoryService.GetKeysValues(MemoryQueryParameters, new List <string>(GetKeysResult),
                                                                          (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->GetKeysValues-1->Error-> " + Message);
            });

            if (!bLocalResult || GetKeysValuesResult == null || GetKeysValuesResult.Count != 2)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeysValues-1 returned " + GetKeysValuesResult?.Count + " results, but expected 2. Error status: " + bLocalResult);
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeysValues-1 has succeed.");

            int ElapsedSeconds = 0;

            while (SubscribeDoneCounter.Get() != NumberOfExpectedSubscriptionMessages && ElapsedSeconds < MaxWaitSecondsForAllSubscriptionMessages && !FailureStatus.Get())
            {
                Thread.Sleep(1000);
                ElapsedSeconds++;
            }
            if (FailureStatus.Get())
            {
                PrintAction?.Invoke("Failure detected. Test failed.");
                return(false);
            }
            if (SubscribeDoneCounter.Get() != NumberOfExpectedSubscriptionMessages)
            {
                PrintAction?.Invoke("Subscription messages timed out or processed multiple time.");
                return(false);
            }
            lock (SubscribeDoneCounter.Monitor)
            {
                SubscribeMessages = SubscribeMessages.OrderBy(q => q).ToList();
                foreach (var Message in SubscribeMessages)
                {
                    PrintAction?.Invoke("Received message: " + Message);
                }
            }

            bLocalResult = true;
            SelectedMemoryService.GetPubSubService().DeleteTopicGlobally(
                MemoryQueryParameters,
                (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->DeleteTopicGlobally-1->Error-> " + Message);
            });
            if (!bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->DeleteTopicGlobally-1 has failed.");
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->DeleteTopicGlobally-1 has succeed.");

            bLocalResult = SelectedMemoryService.SetKeyValue(ExpireTestMemoryQueryParameters, new Tuple <string, BPrimitiveType>[]
            {
                new Tuple <string, BPrimitiveType>("TestKey1", new BPrimitiveType("TestValue1"))
            },
                                                             (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->SetKeyValue-ExpireTest->Error-> " + Message);
            });
            if (!bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->SetKeyValue-ExpireTest has failed.");
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->SetKeyValue-ExpireTest has succeed.");

            bLocalResult = SelectedMemoryService.GetKeyExpireTime(ExpireTestMemoryQueryParameters, out TimeSpan TTL_1,
                                                                  (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->GetKeyExpireTime-ExpireTest-1->Error-> Expected: " + Message);
            });
            if (bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeyExpireTime-ExpireTest-1 did not fail.");
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeyExpireTime-ExpireTest-1 successfully failed.");

            bLocalResult = SelectedMemoryService.SetKeyExpireTime(ExpireTestMemoryQueryParameters, TimeSpan.FromSeconds(2.0f),
                                                                  (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->SetKeyExpireTime-ExpireTest-1->Error-> " + Message);
            });
            if (!bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->SetKeyExpireTime-ExpireTest-1 has failed.");
                return(false);
            }
            ;
            PrintAction?.Invoke("BMemoryPubSubServiceTest->SetKeyExpireTime-ExpireTest-1 has succeed.");

            bLocalResult = SelectedMemoryService.GetKeyExpireTime(ExpireTestMemoryQueryParameters, out TimeSpan TTL_2,
                                                                  (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->GetKeyExpireTime-ExpireTest-2->Error-> " + Message);
            });
            if (!bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeyExpireTime-ExpireTest-2 has failed.");
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeyExpireTime-ExpireTest-2 has succeed.");

            bLocalResult = true;
            var ExpireGetKeyResult_1 = SelectedMemoryService.GetKeyValue(ExpireTestMemoryQueryParameters, "TestKey1",
                                                                         (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->GetKeyValue-ExpireTest-1->Error-> " + Message);
            });

            if (!bLocalResult || ExpireGetKeyResult_1 == null)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeyValue-ExpireTest-1 has failed.");
                return(false);
            }
            if (ExpireGetKeyResult_1.AsString != "TestValue1")
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeyValue-ExpireTest-1 returned unexpected value: " + ExpireGetKeyResult_1?.AsString);
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeyValue-ExpireTest-1 has succeed.");

            Thread.Sleep(2500);

            bLocalResult = SelectedMemoryService.GetKeyExpireTime(ExpireTestMemoryQueryParameters, out TimeSpan TTL_3,
                                                                  (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->GetKeyExpireTime-ExpireTest-3->Error-> Expected: " + Message);
            });
            if (bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeyExpireTime-ExpireTest-3 did not fail.");
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeyExpireTime-ExpireTest-3 successfully failed.");

            var ExpireGetKeyResult_2 = SelectedMemoryService.GetKeyValue(ExpireTestMemoryQueryParameters, "TestKey1",
                                                                         (string Message) =>
            {
                Console.WriteLine("BMemoryPubSubServiceTest->GetKeyValue-ExpireTest-2->Error-> " + Message);
            });

            if (ExpireGetKeyResult_2 != null)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeyValue-ExpireTest-2 did not fail.");
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->GetKeyValue-ExpireTest-2 successfully expired.");

            bLocalResult = true;
            SelectedMemoryService.GetPubSubService().DeleteTopicGlobally(
                ExpireTestMemoryQueryParameters,
                (string Message) =>
            {
                bLocalResult = false;
                Console.WriteLine("BMemoryPubSubServiceTest->DeleteTopicGlobally-2->Error-> " + Message);
            });
            if (!bLocalResult)
            {
                PrintAction?.Invoke("BMemoryPubSubServiceTest->DeleteTopicGlobally-2 has failed.");
                return(false);
            }
            PrintAction?.Invoke("BMemoryPubSubServiceTest->DeleteTopicGlobally-2 has succeed.");

            return(true);
        }
Esempio n. 2
0
            private bool UpdateRightsForUsersUponChangeOnSharing(List <string> _RelevantIdList, Tuple <string, List <string> >[] _RightsRegex, Controller_Rights_Internal.EChangeUserRightsForModelType _Action, Action <string> _ErrorMessageAction = null)
            {
                var WaitFor       = new ManualResetEvent(false);
                var InternalError = new BValue <bool>(false, EBProducerStatus.MultipleProducer);
                var DoneStack     = new ConcurrentStack <bool>();

                for (var i = 0; i < _RelevantIdList.Count; i++)
                {
                    for (var j = 0; j < _RightsRegex.Length; j++)
                    {
                        DoneStack.Push(true);
                    }
                }

                foreach (var ChangeForUserId in _RelevantIdList)
                {
                    var CurrentUserID = ChangeForUserId;
                    foreach (var PathRegex in _RightsRegex)
                    {
                        var CurrentPathRegex = PathRegex;
                        BTaskWrapper.Run(() =>
                        {
                            if (!Controller_AtomicDBOperation.Get().GetClearanceForDBOperation(InnerProcessor, UserDBEntry.DBSERVICE_USERS_TABLE(), CurrentUserID, _ErrorMessageAction))
                            {
                                _ErrorMessageAction?.Invoke("PubSub_To_AuthService->UpdateRightsForUsersUponChangeOnSharing: Atomic operation control has failed for " + UserDBEntry.KEY_NAME_USER_ID + ": " + CurrentUserID);
                                InternalError.Set(true);
                                try { WaitFor.Set(); } catch (Exception) { }
                                return;
                            }
                            try
                            {
                                if (!Controller_Rights_Internal.Get().ChangeBaseUserRight(
                                        out bool _bInternalErrorOccured,
                                        true,/*important to set to true*/
                                        _Action,
                                        CurrentUserID,
                                        CurrentPathRegex.Item1.Replace("{shareeUserId}", ChangeForUserId, StringComparison.InvariantCulture),
                                        _ErrorMessageAction,
                                        CurrentPathRegex.Item2))
                                {
                                    if (_bInternalErrorOccured)
                                    {
                                        InternalError.Set(true);
                                        try { WaitFor.Set(); } catch (Exception) { }
                                        return;
                                    }
                                }
                            }
                            finally
                            {
                                Controller_AtomicDBOperation.Get().SetClearanceForDBOperationForOthers(InnerProcessor, UserDBEntry.DBSERVICE_USERS_TABLE(), CurrentUserID, _ErrorMessageAction);
                            }

                            DoneStack.TryPop(out bool _);
                            if (DoneStack.Count == 0)
                            {
                                try
                                {
                                    WaitFor.Set();
                                }
                                catch (Exception) { }
                            }
                        });
                    }
                }

                try
                {
                    if (_RelevantIdList.Count > 0)
                    {
                        WaitFor.WaitOne();
                    }
                    WaitFor.Close();
                }
                catch (Exception) { }

                //Retry if internal error occured
                return(InternalError.Get() == false);
            }
Esempio n. 3
0
        /// <summary>
        ///
        /// <para>CustomSubscribe:</para>
        ///
        /// <para>Subscribes to given custom topic</para>
        ///
        /// <para>Check <seealso cref="IBPubSubServiceInterface.CustomSubscribe"/> for detailed documentation</para>
        ///
        /// </summary>
        public bool CustomSubscribe(string _CustomTopic, Action <string, string> _OnMessage, Action <string> _ErrorMessageAction = null, bool _SubscribeSingleMessage = false)
        {
            if (_CustomTopic != null && _CustomTopic.Length > 0 && _OnMessage != null && BUtility.CalculateStringMD5(_CustomTopic, out string TopicMD5, _ErrorMessageAction))
            {
                if (EnsureQueueExists(TopicMD5, out string QueueUrl, _ErrorMessageAction))
                {
                    var SubscriptionCancellationVar = new BValue <bool>(false, EBProducerStatus.MultipleProducer);
                    var SubscriptionThread          = new Thread(() =>
                    {
                        Thread.CurrentThread.IsBackground = true;

                        while (!SubscriptionCancellationVar.Get())
                        {
                            ReceiveMessageResponse Response;
                            try
                            {
                                using (var ReceiveMessageTask = SQSClient.ReceiveMessageAsync(QueueUrl))
                                {
                                    ReceiveMessageTask.Wait();
                                    Response = ReceiveMessageTask.Result;
                                }
                            }
                            catch (Exception e)
                            {
                                Response = null;
                                _ErrorMessageAction?.Invoke("BPubSubServiceAWS->CustomSubscribe: " + e.Message + ", Trace: " + e.StackTrace);
                                if (e.InnerException != null && e.InnerException != e)
                                {
                                    _ErrorMessageAction?.Invoke("BPubSubServiceAWS->CustomSubscribe->Inner: " + e.InnerException.Message + ", Trace: " + e.InnerException.StackTrace);
                                }
                            }

                            if (Response == null || Response.Messages == null || Response.Messages.Count == 0)
                            {
                                Thread.Sleep(1000);
                                continue;
                            }

                            var AckDictionary = new Dictionary <string, string>();

                            foreach (var MessageContainer in Response.Messages)
                            {
                                if (MessageContainer != null)
                                {
                                    if (!AckDictionary.ContainsKey(MessageContainer.MessageId))
                                    {
                                        AckDictionary.Add(MessageContainer.MessageId, MessageContainer.ReceiptHandle);
                                    }

                                    string Data = MessageContainer.Body;

                                    if (UniqueMessageDeliveryEnsurer != null)
                                    {
                                        UniqueMessageDeliveryEnsurer.Subscribe_ClearAndExtractTimestampFromMessage(ref Data, out string TimestampHash);

                                        if (UniqueMessageDeliveryEnsurer.Subscription_EnsureUniqueDelivery(_CustomTopic, TimestampHash, _ErrorMessageAction))
                                        {
                                            _OnMessage?.Invoke(_CustomTopic, Data);
                                        }
                                    }
                                    else
                                    {
                                        _OnMessage?.Invoke(_CustomTopic, Data);
                                    }
                                }
                            }

                            var AckArray = new List <DeleteMessageBatchRequestEntry>();
                            foreach (var Current in AckDictionary)
                            {
                                AckArray.Add(new DeleteMessageBatchRequestEntry(Current.Key, Current.Value));
                            }

                            try
                            {
                                using (var DeleteMessageBatchTask = SQSClient.DeleteMessageBatchAsync(QueueUrl, AckArray))
                                {
                                    DeleteMessageBatchTask.Wait();
                                }
                            }
                            catch (Exception e)
                            {
                                _ErrorMessageAction?.Invoke("BPubSubServiceAWS->CustomSubscribe: " + e.Message + ", Trace: " + e.StackTrace);
                                if (e.InnerException != null && e.InnerException != e)
                                {
                                    _ErrorMessageAction?.Invoke("BPubSubServiceAWS->CustomSubscribe->Inner: " + e.InnerException.Message + ", Trace: " + e.InnerException.StackTrace);
                                }
                            }
                        }
                    });
                    SubscriptionThread.Start();

                    lock (SubscriberThreadsDictionaryLock)
                    {
                        SubscriberThreadsDictionary.Add(_CustomTopic, new BTuple <Thread, BValue <bool> >(SubscriptionThread, SubscriptionCancellationVar));
                    }
                    return(true);
                }
            }
            return(false);
        }
Esempio n. 4
0
        public void Run(Action <string> _ServerLogAction = null)
        {
            var bStartSucceed       = new BValue <bool>(false);
            var WaitForFirstSuccess = new ManualResetEvent(false);

            BTaskWrapper.Run(() =>
            {
                var WaitForException = new ManualResetEvent(false);
                int FailureCount     = 0;
                do
                {
                    try
                    {
                        lock (Listener)
                        {
                            Listener.Start();
                        }

                        bStartSucceed.Set(true);
                        try
                        {
                            WaitForFirstSuccess.Set();
                        }
                        catch (Exception) {}

                        FailureCount = 0;

                        try
                        {
                            WaitForException.WaitOne();
                            //Do not close WaitForException! Can be reused.
                        }
                        catch (Exception) { }
                    }
                    catch (Exception e)
                    {
                        _ServerLogAction?.Invoke("BWebService->Run->HttpListener->Start: " + e.Message + ", trace: " + e.Message);

                        try
                        {
                            WaitForException.Set();
                        }
                        catch (Exception) { }

                        Thread.Sleep(1000);
                    }
                } while (++FailureCount < 10);

                try
                {
                    WaitForFirstSuccess.Set(); //When exhausted
                }
                catch (Exception) { }
            });

            try
            {
                WaitForFirstSuccess.WaitOne();
                //Do not close WaitForFirstSuccess! Can be reused.
            }
            catch (Exception) {}

            if (!bStartSucceed.Get())
            {
                _ServerLogAction?.Invoke("BWebService->Run: HttpListener.Start() has failed.");
                return;
            }

            BTaskWrapper.Run(() =>
            {
                _ServerLogAction?.Invoke("BWebserver->Run: Server is running. Listening port " + ServerPort);

                while (Listener.IsListening)
                {
                    HttpListenerContext Context = null;

                    int FailureCount = 0;
                    bool bSuccess;
                    do
                    {
                        try
                        {
                            lock (Listener)
                            {
                                Context = Listener.GetContext();
                            }
                            bSuccess     = true;
                            FailureCount = 0;
                        }
                        catch (Exception e)
                        {
                            _ServerLogAction?.Invoke("BWebService->Run->HttpListener->GetContext: " + e.Message + ", trace: " + e.Message);
                            bSuccess = false;
                            Thread.Sleep(1000);
                        }
                    } while (!bSuccess && ++FailureCount < 10);

                    if (Context == null)
                    {
                        continue;
                    }

                    BTaskWrapper.Run(() =>
                    {
                        if (Context == null)
                        {
                            return;
                        }
                        try
                        {
                            Context.Response.AppendHeader("Access-Control-Allow-Origin", "*");

                            bool bIsWebhookRequest =
                                BWebUtilities.DoesContextContainHeader(out List <string> _, out string _, Context, "webhook-request-callback") &&
                                BWebUtilities.DoesContextContainHeader(out List <string> _, out string _, Context, "webhook-request-origin");

                            if (Context.Request.HttpMethod == "OPTIONS" && !bIsWebhookRequest)
                            {
                                Context.Response.AppendHeader("Access-Control-Allow-Headers", "*");
                                Context.Response.AppendHeader("Access-Control-Allow-Credentials", "true");
                                Context.Response.AppendHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH");
                                Context.Response.AppendHeader("Access-Control-Max-Age", "-1");
                                Context.Response.StatusCode = BWebResponse.Status_OK_Code;
                            }
                            else
                            {
                                if (PrefixesToListen == null)
                                {
                                    _ServerLogAction?.Invoke("BWebserver->Run: PrefixesToListen is null.");
                                    WriteInternalError(Context.Response, "Code: WS-PTLN.");
                                    return;
                                }
                                if (!LookForListenersFromRequest(out BWebServiceBase _Callback, Context))
                                {
                                    if (Context.Request.RawUrl.EndsWith("/ping"))
                                    {
                                        WriteOK(Context.Response, "pong");
                                        return;
                                    }
                                    _ServerLogAction?.Invoke($"BWebserver->Run: Request is not being listened. Request: {Context.Request.RawUrl}");
                                    WriteNotFound(Context.Response, "Request is not being listened.");
                                    return;
                                }

                                var Response = _Callback.OnRequest(Context, _ServerLogAction);

                                Context.Response.StatusCode = Response.StatusCode;

                                foreach (var CurrentHeader in Response.Headers)
                                {
                                    foreach (var Value in CurrentHeader.Value)
                                    {
                                        if (CurrentHeader.Key.ToLower() != "access-control-allow-origin")
                                        {
                                            Context.Response.AppendHeader(CurrentHeader.Key, Value);
                                        }
                                    }
                                }

                                if (Response.ResponseContentType != null)
                                {
                                    Context.Response.ContentType = Response.ResponseContentType;
                                }

                                if (Response.ResponseContent.Type == EBStringOrStreamEnum.String)
                                {
                                    byte[] Buffer = Encoding.UTF8.GetBytes(Response.ResponseContent.String);
                                    if (Buffer != null)
                                    {
                                        Context.Response.ContentLength64 = Buffer.Length;
                                        if (Buffer.Length > 0)
                                        {
                                            Context.Response.OutputStream.Write(Buffer, 0, Buffer.Length);
                                        }
                                    }
                                    else
                                    {
                                        Context.Response.ContentLength64 = 0;
                                    }
                                }
                                else
                                {
                                    if (Response.ResponseContent.Stream != null && Response.ResponseContent.StreamLength > 0)
                                    {
                                        Context.Response.ContentLength64 = Response.ResponseContent.StreamLength;
                                        Response.ResponseContent.Stream.CopyTo(Context.Response.OutputStream);
                                    }
                                    else
                                    {
                                        _ServerLogAction?.Invoke("BWebserver->Error: Response is stream, but stream object is " + (Response.ResponseContent.Stream == null ? "null" : "valid") + " and content length is " + Response.ResponseContent.StreamLength);
                                        WriteInternalError(Context.Response, "Code: WS-STRMINV.");
                                        return;
                                    }
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            try
                            {
                                WriteInternalError(Context.Response, "An unexpected internal error has occured: " + e.Message);
                            }
                            catch (Exception) { }

                            _ServerLogAction?.Invoke("Uncaught exception in the request handle: " + e.Message + ", trace: " + e.StackTrace);
                        }
                        finally
                        {
                            //Always close the stream
                            try { Context.Response.OutputStream.Close(); } catch (Exception) { }
                            try { Context.Response.OutputStream.Dispose(); } catch (Exception) { }
                            //try { Context.Response.Close(); } catch (Exception) { }
                        }
                    });
                }
            });
        }
Esempio n. 5
0
            private bool GetUserListFromAzure(out List <UserPrincipal> _Users, string _TokenType, string _AccessToken, Action <string> _ErrorMessageAction)
            {
                _Users = null;

                using var Handler = new HttpClientHandler
                      {
                          SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls,
                          ServerCertificateCustomValidationCallback = (a, b, c, d) => true
                      };
                using var Client = new HttpClient(Handler);
                Client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", _TokenType + " " + _AccessToken);

                string ResponseString = "";

                try
                {
                    using var RequestTask = Client.GetAsync("https://graph.microsoft.com/v1.0/servicePrincipals/" + FetchUsersAppObjectID + "/appRoleAssignedTo");
                    RequestTask.Wait();

                    using var Response        = RequestTask.Result;
                    using var ResponseContent = Response.Content;

                    using var ReadResponseTask = ResponseContent.ReadAsStringAsync();
                    ReadResponseTask.Wait();

                    ResponseString = ReadResponseTask.Result;

                    if (!Response.IsSuccessStatusCode)
                    {
                        _ErrorMessageAction?.Invoke("GetUserListFromAzure->Error: " + ResponseString);
                        return(false);
                    }

                    var Parsed = JObject.Parse(ResponseString);

                    if (!Parsed.TryGetValue("value", out JToken Values) || Values.Type != JTokenType.Array)
                    {
                        _ErrorMessageAction?.Invoke("GetTokenForAzure->Error: Unexpected response: " + ResponseString);
                        return(false);
                    }

                    var UsersResult = new List <UserPrincipal>();

                    var ValuesArray = Values as JArray;

                    var InternalFailure = new BValue <bool>(false, EBProducerStatus.MultipleProducer);
                    var WaitFor         = new ManualResetEvent(false);
                    var RemainedTasks   = new ConcurrentStack <bool>();
                    for (var i = 0; i < ValuesArray.Count; i++)
                    {
                        RemainedTasks.Push(true);
                    }

                    foreach (var Value in ValuesArray)
                    {
                        if (Value.Type != JTokenType.Object)
                        {
                            _ErrorMessageAction?.Invoke("GetTokenForAzure->Error: Unexpected response: " + ResponseString);
                            return(false);
                        }
                        var ValueObject = (JObject)Value;

                        if (!ValueObject.TryGetValue("principalDisplayName", out JToken UserNameToken) || UserNameToken.Type != JTokenType.String ||
                            !ValueObject.TryGetValue("principalId", out JToken PrincipleIDToken) || PrincipleIDToken.Type != JTokenType.String)
                        {
                            _ErrorMessageAction?.Invoke("GetTokenForAzure->Error: Unexpected response: " + ResponseString);
                            return(false);
                        }

                        var UserName    = (string)UserNameToken;
                        var PrincipalId = (string)PrincipleIDToken;

                        BTaskWrapper.Run(() =>
                        {
                            if (!GetUserEmail(out string UserEmail, PrincipalId, _TokenType, _AccessToken, _ErrorMessageAction))
                            {
                                InternalFailure.Set(true);
                                WaitFor.Set();
                                return;
                            }

                            if (InternalFailure.Get())
                            {
                                return;
                            }

                            lock (UsersResult)
                            {
                                UsersResult.Add(new UserPrincipal()
                                {
                                    Name  = UserName,
                                    Email = UserEmail
                                });
                            }

                            RemainedTasks.TryPop(out bool _);
                            if (RemainedTasks.Count == 0)
                            {
                                WaitFor.Set();
                            }
                        });
                    }

                    if (ValuesArray.Count > 0)
                    {
                        try { WaitFor.WaitOne(); } catch (Exception) { }
                    }
                    try { WaitFor.Close(); } catch (Exception) { }

                    if (InternalFailure.Get())
                    {
                        _ErrorMessageAction?.Invoke("GetUserListFromAzure->Error: Get user e-mail step has failed.");
                        return(false);
                    }

                    _Users = UsersResult;
                }
                catch (Exception e)
                {
                    if (e.InnerException != null && e.InnerException != e)
                    {
                        _ErrorMessageAction?.Invoke("GetUserListFromAzure->Error: Inner: " + e.InnerException.Message + ", Trace: " + e.InnerException.StackTrace);
                    }
                    if (e is AggregateException)
                    {
                        foreach (var Inner in (e as AggregateException).InnerExceptions)
                        {
                            _ErrorMessageAction?.Invoke("GetUserListFromAzure->Error: Aggregate->Inner: " + Inner.Message + ", Trace: " + Inner.StackTrace);
                        }
                    }
                    _ErrorMessageAction?.Invoke("GetUserListFromAzure->Error: " + ResponseString + ", message: " + e.Message + ", trace: " + e.StackTrace);
                    return(false);
                }
                return(true);
            }
Esempio n. 6
0
        /// <summary>
        ///
        /// <para>CustomSubscribe:</para>
        ///
        /// <para>Subscribes to given custom topic</para>
        ///
        /// <para>Check <seealso cref="IBPubSubServiceInterface.CustomSubscribe"/> for detailed documentation</para>
        ///
        /// </summary>
        public bool CustomSubscribe(
            string _CustomTopic,
            Action <string, string> _OnMessage,
            Action <string> _ErrorMessageAction = null, bool _SubscribeSingleMessage = false)
        {
            if (_CustomTopic != null && _CustomTopic.Length > 0 && _OnMessage != null)
            {
                _CustomTopic = GetGoogleFriendlyTopicName(_CustomTopic);

                if (GetSubscriber(out SubscriberServiceApiClient APIClientVar, out SubscriptionName SubscriptionNameVar, _CustomTopic, _ErrorMessageAction))
                {
                    var SubscriptionCancellationVar = new BValue <bool>(false, EBProducerStatus.MultipleProducer);
                    var SubscriptionThread          = new Thread(() =>
                    {
                        Thread.CurrentThread.IsBackground = true;

                        while (!SubscriptionCancellationVar.Get())
                        {
                            PullResponse Response = null;
                            try
                            {
                                Response = APIClientVar.Pull(SubscriptionNameVar, true, 1000);
                            }
                            catch (Exception e)
                            {
                                if (e is RpcException && (e as RpcException).StatusCode == StatusCode.DeadlineExceeded)
                                {
                                    Thread.Sleep(1000);
                                    continue;
                                }

                                Response = null;

                                _ErrorMessageAction?.Invoke("BPubSubServiceGC->CustomSubscribe: " + e.Message + ", Trace: " + e.StackTrace);
                                if (e.InnerException != null && e.InnerException != e)
                                {
                                    _ErrorMessageAction?.Invoke("BPubSubServiceGC->CustomSubscribe->Inner: " + e.InnerException.Message + ", Trace: " + e.InnerException.StackTrace);
                                }
                            }

                            if (Response == null || Response.ReceivedMessages == null || !Response.ReceivedMessages.Any())
                            {
                                Thread.Sleep(1000);
                                continue;
                            }

                            var MessageContainers = Response.ReceivedMessages.ToArray();
                            if (MessageContainers != null && MessageContainers.Length > 0)
                            {
                                var AckArray = new List <string>();

                                foreach (var MessageContainer in MessageContainers)
                                {
                                    if (MessageContainer != null)
                                    {
                                        if (!AckArray.Contains(MessageContainer.AckId))
                                        {
                                            AckArray.Add(MessageContainer.AckId);
                                        }

                                        string Topic = GetTopicNameFromGoogleFriendlyName(_CustomTopic);
                                        string Data  = MessageContainer.Message.Data.ToStringUtf8();

                                        if (UniqueMessageDeliveryEnsurer != null)
                                        {
                                            UniqueMessageDeliveryEnsurer.Subscribe_ClearAndExtractTimestampFromMessage(ref Data, out string TimestampHash);

                                            if (UniqueMessageDeliveryEnsurer.Subscription_EnsureUniqueDelivery(Topic, TimestampHash, _ErrorMessageAction))
                                            {
                                                _OnMessage?.Invoke(Topic, Data);
                                            }
                                        }
                                        else
                                        {
                                            _OnMessage?.Invoke(Topic, Data);
                                        }
                                    }
                                }

                                try
                                {
                                    APIClientVar.Acknowledge(SubscriptionNameVar, AckArray);
                                }
                                catch (Exception e)
                                {
                                    if (e is RpcException && (e as RpcException).Status.StatusCode == StatusCode.InvalidArgument)
                                    {
                                        //That is fine, probably due to previous subscriptions
                                    }
                                    else
                                    {
                                        _ErrorMessageAction?.Invoke("BPubSubServiceGC->CustomSubscribe: " + e.Message + ", Trace: " + e.StackTrace);
                                        if (e.InnerException != null && e.InnerException != e)
                                        {
                                            _ErrorMessageAction?.Invoke("BPubSubServiceGC->CustomSubscribe->Inner: " + e.InnerException.Message + ", Trace: " + e.InnerException.StackTrace);
                                        }
                                    }
                                }
                            }
                        }
                    });
                    SubscriptionThread.Start();

                    lock (SubscriberThreadsDictionaryLock)
                    {
                        SubscriberThreadsDictionary.Add(SubscriptionNameVar, new BTuple <Thread, BValue <bool> >(SubscriptionThread, SubscriptionCancellationVar));
                    }
                    return(true);
                }
            }
            return(false);
        }
Esempio n. 7
0
        public bool CustomSubscribe(string _CustomTopic, Action <string, string> _OnMessage, Action <string> _ErrorMessageAction = null, bool _SubscribeSingleMessage = false)
        {
            if (_CustomTopic != null && _CustomTopic.Length > 0 &&
                _OnMessage != null)
            {
                _CustomTopic = GetAzureFriendlyTopicName(_CustomTopic);

                if (EnsureTopicExists(_CustomTopic, out ITopicClient _TopicClient, _ErrorMessageAction))
                {
                    if (EnsureSubscriptionExists(_CustomTopic, _TopicClient, out Microsoft.Azure.ServiceBus.ISubscriptionClient _SubscriptionClient, _ErrorMessageAction))
                    {
                        var SubscriptionCancellationVar = new BValue <bool>(false, EBProducerStatus.MultipleProducer);
                        var SubscriptionThread          = new Thread(() =>
                        {
                            Thread.CurrentThread.IsBackground = true;
                            try
                            {
                                // Define exception receiver handler
                                Func <ExceptionReceivedEventArgs, Task> ExceptionReceiverHandler = (ExceptionReceivedEventArgs _EventArgs) =>
                                {
                                    _ErrorMessageAction?.Invoke($"BPubSubServiceAzure->CustomSubscribe->ExceptionReceiverHandler: {_EventArgs.Exception.Message}, Action: {_EventArgs.ExceptionReceivedContext.Action}, EntityPath: {_EventArgs.ExceptionReceivedContext.EntityPath}, Endpoint: {_EventArgs.ExceptionReceivedContext.Endpoint}, ClientId: {_EventArgs.ExceptionReceivedContext.ClientId}, Trace: {_EventArgs.Exception.StackTrace}");

                                    RemoveSubscriberThread(_CustomTopic);
                                    if (!_SubscriptionClient.IsClosedOrClosing)
                                    {
                                        using (var CloseSubscriptionTask = _SubscriptionClient.CloseAsync())
                                        {
                                            CloseSubscriptionTask.Wait();
                                        }
                                    }

                                    return(Task.CompletedTask);
                                };

                                // Configure the message handler options in terms of exception handling, number of concurrent messages to deliver, etc.
                                var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceiverHandler)
                                {
                                    // Maximum number of concurrent calls to the callback ProcessMessagesAsync(), set to 1 for simplicity.
                                    // Set it according to how many messages the application wants to process in parallel.
                                    MaxConcurrentCalls = 1,

                                    // Indicates whether the message pump should automatically complete the messages after returning from user callback.
                                    // False below indicates the complete operation is handled by the user callback as in ProcessMessagesAsync().
                                    AutoComplete = false
                                };

                                // Register the function that processes messages.
                                _SubscriptionClient.RegisterMessageHandler(async(Message MessageContainer, CancellationToken token) =>
                                {
                                    if (MessageContainer != null)
                                    {
                                        string Topic = GetTopicNameFromAzureFriendlyName(_CustomTopic);
                                        string Data  = Encoding.UTF8.GetString(MessageContainer.Body);

                                        if (MessageContainer.Label != null &&
                                            MessageContainer.Label.Equals(_CustomTopic))
                                        {
                                            _ErrorMessageAction?.Invoke("BPubSubServiceAzure->CustomSubscribe: Received [Internal] pub/sub message.");
                                        }
                                        else
                                        {
                                            _ErrorMessageAction?.Invoke("BPubSubServiceAzure->CustomSubscribe: Received [StorageAccount] pub/sub message.");
                                        }

                                        if (UniqueMessageDeliveryEnsurer != null)
                                        {
                                            UniqueMessageDeliveryEnsurer.Subscribe_ClearAndExtractTimestampFromMessage(ref Data, out string TimestampHash);

                                            if (UniqueMessageDeliveryEnsurer.Subscription_EnsureUniqueDelivery(Topic, TimestampHash, _ErrorMessageAction))
                                            {
                                                _OnMessage?.Invoke(Topic, Data);
                                                RemoveSubscriberThread(_CustomTopic);
                                                if (!_SubscriptionClient.IsClosedOrClosing)
                                                {
                                                    await _SubscriptionClient.CloseAsync();
                                                }
                                            }
                                        }
                                        else
                                        {
                                            _OnMessage?.Invoke(Topic, Data);
                                        }

                                        await _SubscriptionClient.CompleteAsync(MessageContainer.SystemProperties.LockToken);

                                        if (_SubscribeSingleMessage)
                                        {
                                            RemoveSubscriberThread(_CustomTopic);
                                            if (!_SubscriptionClient.IsClosedOrClosing)
                                            {
                                                await _SubscriptionClient.CloseAsync();
                                            }
                                        }
                                    }
                                }, messageHandlerOptions);
                            }
                            catch (Exception e)
                            {
                                _ErrorMessageAction?.Invoke("BPubSubServiceAzure->CustomSubscribe: " + e.Message + ", Trace: " + e.StackTrace);
                                if (e.InnerException != null && e.InnerException != e)
                                {
                                    _ErrorMessageAction?.Invoke("BPubSubServiceAzure->CustomSubscribe->InnerException: " + e.InnerException.Message + ", Trace: " + e.InnerException.StackTrace);
                                }

                                RemoveSubscriberThread(_CustomTopic);
                                if (!_SubscriptionClient.IsClosedOrClosing)
                                {
                                    using (var CloseSubscriptionTask = _SubscriptionClient.CloseAsync())
                                    {
                                        CloseSubscriptionTask.Wait();
                                    }
                                }
                            }

                            while (!SubscriptionCancellationVar.Get())
                            {
                                //Wait until delete
                                Thread.Sleep(500);
                            }

                            if (!_SubscriptionClient.IsClosedOrClosing)
                            {
                                using (var CloseSubscriptionTask = _SubscriptionClient.CloseAsync())
                                {
                                    CloseSubscriptionTask.Wait();
                                }
                            }
                        });
                        SubscriptionThread.Start();

                        lock (SubscriberThreadsDictionaryLock)
                        {
                            SubscriberThreadsDictionary.Add(_CustomTopic, new BTuple <Thread, BValue <bool> >(SubscriptionThread, SubscriptionCancellationVar));
                        }
                        return(true);
                    }
                }
            }
            return(false);
        }