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; } }
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); }
/// <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(); }
/// <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(); }
private void OnPauseTimerElapsedTime(object source, ElapsedEventArgs e) { pauseTimer.Enabled = false; processing = false; status = SubscriberStatus.Started; if (readQueue != null) { readQueue.BeginPeek(); } }
/// <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)); }
/// <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; }
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."); }
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."); }
/// <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(); }
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."); }
/// <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); }