示例#1
0
        internal Subscriber(SubscriptionSettings settings, MessageQueue readQueue, MessageQueue errorQueue, ILogger logger)
        {
            if (settings == null)
            {
                throw new ArgumentNullException(nameof(settings));
            }
            if (readQueue == null)
            {
                throw new ArgumentNullException(nameof(readQueue));
            }
            if (logger == null)
            {
                throw new ArgumentNullException(nameof(logger));
            }

            logger.Trace($"{nameof(Subscriber)}() - [ctor]");

            status          = SubscriberStatus.Stopped;
            this.settings   = settings;
            this.readQueue  = readQueue;
            this.errorQueue = errorQueue;
            this.log        = logger;

            maxFailedAttemps = settings.AttemptsBeforeFail;

            if (settings.PauseOnError)
            {
                pauseTimer          = new System.Timers.Timer(settings.SecondsToPause * 1000);
                pauseTimer.Elapsed += OnPauseTimerElapsedTime;
            }
        }
示例#2
0
            private Result CreateResult(SubscriberStatus status, Exception exception)
            {
                var result = (Result)typeof(Events.Subscribe.Result).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[0], null).Invoke(null);

                typeof(Result).GetProperty("Status", BindingFlags.Public | BindingFlags.Instance).SetValue(result, status);
                typeof(Result).GetProperty("Exception", BindingFlags.Public | BindingFlags.Instance).SetValue(result, exception);
                typeof(Result).GetProperty("Reason", BindingFlags.Public | BindingFlags.Instance).SetValue(result, "Blah blah");
                return(result);
            }
示例#3
0
        /// <summary>
        /// 取消订阅
        /// </summary>
        public virtual void UnSubscriber()
        {
            if (this.Status == SubscriberStatus.Exit || this.Status == SubscriberStatus.Error || this.Status == SubscriberStatus.UnSubscribe)
            {
                return;
            }

            this.Status = SubscriberStatus.UnSubscribe;
            CancellationTokenSource.Cancel();
        }
示例#4
0
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="name">订阅者名称</param>
        /// <param name="publisherName">发布者名称</param>
        /// <param name="waitTimeout">等待超时时间,单位:分钟</param>
        public Subscriber(string name, string publisherName, TimeSpan waitTimeout)
        {
            Name                         = name;
            PublisherName                = publisherName;
            this.Status                  = SubscriberStatus.Init;
            this.waitTimeout             = waitTimeout;
            this.cancellationTokenSource = new CancellationTokenSource();

            Init();
        }
示例#5
0
        private void OnPauseTimerElapsedTime(object source, ElapsedEventArgs e)
        {
            pauseTimer.Enabled = false;
            processing         = false;
            status             = SubscriberStatus.Started;

            if (readQueue != null)
            {
                readQueue.BeginPeek();
            }
        }
示例#6
0
        /// <summary>
        /// Get a subscriber by external_id.
        /// </summary>
        /// <param name="external_id"></param>
        /// <param name="subscriberStatus"></param>
        /// <returns></returns>
        public string GetSubscriberByExternal_id(string external_id, SubscriberStatus subscriberStatus = SubscriberStatus.active)
        {
            string MyReturn = string.Empty;

            // Example:
            // GET https://api.us.newsweaver.com/v2/{account code}/subscribers?ext_id=11019&status=all

            string MyURL = BaseURL + AccountCode + $"/subscribers/?ext_id={external_id}&status={subscriberStatus}";

            return(MakeHttpWebRequest(MyURL, HttpVerb.GET));
        }
示例#7
0
        /// <summary>
        /// 初始化
        /// </summary>
        private void Init()
        {
            this.semaphore = new Semaphore(0, 1, PublisherName, out bool createNew);

            if (createNew)
            {
                this.Status = SubscriberStatus.Error;
                Semaphore.Dispose();
                throw new InvalidOperationException("Publisher不存在");
            }

            this.Status = SubscriberStatus.Ready;
        }
示例#8
0
        public void Start()
        {
            log.Trace($"{nameof(Start)}() started.");
            log.Info($"Attemting to start subscriber for queue: {readQueue.Path}");

            if (status != SubscriberStatus.Paused && status != SubscriberStatus.Stopped)
            {
                log.Error($"Attempt to start subscription failed. {nameof(Start)}() method was called when status was : {status.ToString()}.");
                throw new InvalidOperationException($"Subscriber cannot be started. Current state is: {status.ToString()}.");
            }

            try
            {
                status = SubscriberStatus.Starting;

                if (!onCompleteRegistered)
                {
                    log.Trace("Registering OnPeakComplete.");
                    readQueue.PeekCompleted += OnPeakComplete;
                    onCompleteRegistered     = true;
                }
                else
                {
                    log.Trace("OnPeakComplete event already registered.");
                }

                readQueue.BeginPeek();
                status = SubscriberStatus.Started;

                log.Info($"Subscriber {readQueue.Path} started.");
            }
            catch (Exception ex)
            {
                status = SubscriberStatus.Stopped;
                log.Error($"Error while attemtping to start subscriber: {ex.Message}", ex);
                throw ex;
            }

            log.Trace($"{nameof(Start)}() complete.");
        }
示例#9
0
        public void Stop()
        {
            log.Trace($"{nameof(Stop)}() started.");
            log.Info($"Attemting to stop subscriber for queue: {readQueue.Path}");

            status = SubscriberStatus.Stopping;
            if (processing)
            {
                readyToStop.WaitOne();
            }

            if (onCompleteRegistered)
            {
                readQueue.PeekCompleted -= OnPeakComplete;
                onCompleteRegistered     = false;
            }

            status = SubscriberStatus.Stopped;
            log.Info($"Subscriber {readQueue.Path} stopped.");

            log.Trace($"{nameof(Stop)}() completed.");
        }
示例#10
0
        /// <summary>
        /// 等待通知
        /// </summary>
        /// <param name="callback">收到通知后的回调</param>
        /// <param name="completedCallback"></param>
        /// <returns></returns>
        public virtual void StartWaitNotice(Action callback, Action <SubscribeCompletedInfo> completedCallback = null)
        {
            if (callback == null)
            {
                this.Status = SubscriberStatus.Error;
                throw new ArgumentException("callback不能为null");
            }

            if (this.Status != SubscriberStatus.Ready)
            {
                this.Status = SubscriberStatus.Error;
                throw new InvalidOperationException("只有状态为Ready时才能启动等待通知");
            }

            var task = new Task(() =>
            {
                while (!CancellationTokenSource.IsCancellationRequested)
                {
                    this.Status = SubscriberStatus.Waitting;

                    var hasSemaphore = Semaphore.WaitOne(WaitTimeout);

                    if (hasSemaphore)
                    {
                        this.Status = SubscriberStatus.Processing;

                        callback();
                    }
                }
            }, CancellationTokenSource.Token);

            task.ContinueWith(t =>
            {
                this.Status = t.Exception == null ? SubscriberStatus.Exit : SubscriberStatus.Error;
                completedCallback?.Invoke(new SubscribeCompletedInfo(this, t.Exception?.InnerException));
            });

            task.Start();
        }
示例#11
0
        private void OnPeakComplete(object sender, PeekCompletedEventArgs e)
        {
            log.Trace($"{nameof(OnPeakComplete)} started.");

            bool ignoreError = false;

            if (status != SubscriberStatus.Started)
            {
                processing = false;
                log.Trace($"{nameof(OnPeakComplete)} complete without processing.");
                return;
            }

            Message message = null;

            processing = true;

            try
            {
                message = readQueue.EndPeek(e.AsyncResult);

                if (settings.DequeueBeforeHandling)
                {
                    message = readQueue.Receive();
                }


                log.Trace($"Excuting handler on message id: {message.Id} - label: {message.Label}");

                settings.MessageHandler.Method.Invoke(settings.MessageHandler.Target, new object[] { message.Body });

                log.Trace("Handler execution complete.");

                if (!settings.DequeueBeforeHandling)
                {
                    log.Trace($"Removing message from queue: {message.Id} - label: {message.Label}");
                    readQueue.Receive();
                }

                // done with message
                log.Trace("");
                this.failedAttemps = 0;
            }
            catch (Exception ex)
            {
                failedAttemps++;

                if (settings.AttemptsBeforeFail > 1)
                {
                    if (failedAttemps < settings.AttemptsBeforeFail)
                    {
                        log.Warn($"Error processing message. Attempt {failedAttemps}/{maxFailedAttemps}. Error: {GetMessageFromException(ex)}");
                        ignoreError = true;
                    }
                }

                if (!ignoreError)
                {
                    if (settings.PauseOnError)
                    {
                        log.Warn($"Subscriber will pause message processing for {settings.SecondsToPause} seconds.");
                        status             = SubscriberStatus.Paused;
                        pauseTimer.Enabled = true;
                    }
                    else
                    {
                        log.Error($"Error processing message. {failedAttemps}/{maxFailedAttemps} Failed attempts. Error{GetMessageFromException(ex)}", ex);

                        if (errorQueue == null)
                        {
                            log.Warn("Error queue is not set. Message can't be moved out of queue. Stopping subscriber.");
                            status = SubscriberStatus.Stopped;
                        }
                        else
                        {
                            MoveToErrorQueue(message);
                        }
                    }

                    failedAttemps = 0;
                }
            }


            try
            {
                readQueue.Refresh();

                if (status == SubscriberStatus.Started & (pauseTimer == null || !pauseTimer.Enabled))
                {
                    readQueue.BeginPeek();
                }
            }
            catch (Exception ex)
            {
                log.Error($"Error refreshing queue: {ex.Message}", ex);
            }

            processing = false;
            readyToStop.Set();

            log.Trace($"{nameof(OnPeakComplete)} complete.");
        }
示例#12
0
        /// <summary>
        /// Get a subscriber by external_id.
        /// </summary>
        /// <param name="external_id"></param>
        /// <param name="subscriberStatus"></param>
        /// <returns></returns>
        public async Task <string> GetSubscriberByExternal_idAsync(string external_id, SubscriberStatus subscriberStatus = SubscriberStatus.active)
        {
            //Documentation: https://developer.poppulo.com/api-calls/api-list-subscribers.html

            string MyURL = BaseURL + AccountCode + string.Format(@"/subscribers/?ext_id={0}&status={1}", external_id, subscriberStatus);

            using (HttpResponseMessage r = await HTTPClientSendAsync(url: MyURL, method: HttpMethod.Get))
            {
                using (HttpContent c = r.Content)
                {
                    return(await c.ReadAsStringAsync());
                }
            }
        }
        /// <summary>
        /// Gets the list subscribers.
        /// </summary>
        /// <param name="id">The identifier.</param>
        /// <param name="limit">The limit.</param>
        /// <param name="page">The page.</param>
        /// <param name="firstName">The first name to search for in the list.</param>
        /// <param name="lastName">The last name to search for in the list.</param>
        /// <param name="mobileNumber">The mobile number to search for in the list.</param>
        /// <param name="searchOperator">The search operator to use if multiple search params are provided.</param>
        /// <returns></returns>
        public SubscribersResponse GetListSubscribers(int id, int?limit = null, int?page = null, string firstName = null, string lastName = null, string mobileNumber = null, SearchOperator searchOperator = SearchOperator.AND, SubscriberStatus status = SubscriberStatus.ACTIVE)
        {
            var request = new RestRequest($"lists/{id}/subscribers");

            request.Method = Method.GET;

            if (limit.HasValue)
            {
                request.AddParameter("limit", limit, ParameterType.GetOrPost);
            }

            if (page.HasValue)
            {
                request.AddParameter("page", page, ParameterType.GetOrPost);
            }

            var searchParams = 0;

            if (!string.IsNullOrWhiteSpace(firstName))
            {
                request.AddParameter("first", firstName, ParameterType.GetOrPost);
                searchParams = searchParams + 1;
            }

            if (!string.IsNullOrWhiteSpace(lastName))
            {
                request.AddParameter("last", lastName, ParameterType.GetOrPost);
                searchParams = searchParams + 1;
            }

            if (!string.IsNullOrWhiteSpace(mobileNumber))
            {
                request.AddParameter("mobile_number", mobileNumber, ParameterType.GetOrPost);
                searchParams = searchParams + 1;
            }

            request.AddParameter("status", status.ToString(), ParameterType.GetOrPost);
            searchParams = searchParams + 1;

            if (searchParams > 1)
            {
                request.AddParameter("operator", searchOperator.ToString(), ParameterType.GetOrPost);
            }

            return(Execute <SubscribersResponse>(request));
        }
        /// <summary>
        /// Gets all subscribers.
        /// </summary>
        /// <param name="firstName">The first name to search for.</param>
        /// <param name="lastName">The last name to search for.</param>
        /// <param name="mobileNumber">The mobile number to search for.</param>
        /// <param name="searchOperator">The search operator to use if multiple search params are provided.</param>
        /// <returns></returns>
        public List <Subscriber> GetAllSubscribers(string firstName = null, string lastName = null, string mobileNumber = null, SearchOperator searchOperator = SearchOperator.AND, SubscriberStatus status = SubscriberStatus.ACTIVE)
        {
            var subscribers = new List <Subscriber>();
            var response    = GetSubscribers(firstName: firstName, lastName: lastName, mobileNumber: mobileNumber, searchOperator: searchOperator, status: status);

            if (response != null && response.Count > 0)
            {
                subscribers.AddRange(response.Data);

                if (response.Pages > 1)
                {
                    var limit      = response.Limit;
                    var page       = response.CurrentPage;
                    var totalPages = response.Total;

                    while (page <= totalPages)
                    {
                        page++;
                        response = GetSubscribers(limit, page, firstName, lastName, mobileNumber, searchOperator, status);
                        subscribers.AddRange(response.Data);
                    }
                }
            }

            return(subscribers);
        }