public void WhenSearch_ThenReturnsActiveSubscriptions()
            {
                var config = new SubscriptionRelayConfig
                {
                    Config = new SubscriptionConfig
                    {
                        Url = "aurl"
                    }
                };

                store.Setup(s => s.Search("aneventname", true))
                .Returns(new List <SubscriptionRelayConfig>
                {
                    config
                });

                var result = service.Get(new SearchSubscriptions
                {
                    EventName = "aneventname"
                });

                Assert.That(result.Subscribers.Count, Is.EqualTo(1));
                Assert.That(result.Subscribers[0], Is.EqualTo(config));
                store.Verify(s => s.Search("aneventname", true));
            }
            public void WhenWrite_ThenPostsEventToSubscribers()
            {
                var config = new SubscriptionRelayConfig();

                subscriptionCache.Setup(sc => sc.GetAll(It.IsAny <string>()))
                .Returns(new List <SubscriptionRelayConfig>
                {
                    config
                });

                var result = processor.ProcessMessage(new WebhookEvent
                {
                    EventName = "aneventname",
                    Data      = "adata"
                });

                Assert.That(result, Is.True);
                subscriptionCache.Verify(sc => sc.GetAll("aneventname"));
                serviceClient.VerifySet(sc => sc.Retries = EventRelayQueueProcessor.DefaultServiceClientRetries);
                serviceClient.VerifySet(sc => sc.Timeout = TimeSpan.FromSeconds(EventRelayQueueProcessor.DefaultServiceClientTimeoutSeconds));
                serviceClient.Verify(sc => sc.Relay(config, It.Is <WebhookEvent>(whe =>
                                                                                 whe.Data.ToString() == "adata" &&
                                                                                 whe.EventName == "aneventname"
                                                                                 )));
            }
            public void WhenWrite_ThenPostsEventToSubscribersAndUpdatesResults()
            {
                var config = new SubscriptionRelayConfig();

                subscriptionCache.Setup(sc => sc.GetAll(It.IsAny <string>()))
                .Returns(new List <SubscriptionRelayConfig>
                {
                    config
                });
                var result = new SubscriptionDeliveryResult();

                serviceClient.Setup(sc => sc.Relay(config, It.IsAny <WebhookEvent>()))
                .Returns(result);

                processor.ProcessMessage(new WebhookEvent
                {
                    EventName = "aneventname",
                    Data      = new Dictionary <string, string> {
                        { "akey", "avalue" }
                    }
                });

                subscriptionService.Verify(ss => ss.UpdateResults(It.Is <List <SubscriptionDeliveryResult> >(results =>
                                                                                                             results.Count == 1 &&
                                                                                                             results[0] == result)));
            }
        /// <summary>
        ///     Creates an instance of a serviceclient and configures it to send an event notification.
        ///     See: https://developer.github.com/webhooks/#payloads for specification
        /// </summary>
        private IServiceClient CreateServiceClient(SubscriptionRelayConfig relayConfig, string eventName, TimeSpan?timeout)
        {
            try
            {
                var client = ServiceClientFactory.Create(relayConfig.Config.Url);
                client.Timeout       = timeout;
                client.RequestFilter = request =>
                {
                    request.ContentType = MimeTypes.Json;
                    request.Headers.Remove(WebhookEventConstants.SecretSignatureHeaderName);
                    request.Headers.Remove(WebhookEventConstants.RequestIdHeaderName);
                    request.Headers.Remove(WebhookEventConstants.EventNameHeaderName);

                    if (relayConfig.Config.ContentType.HasValue())
                    {
                        request.ContentType = relayConfig.Config.ContentType;
                    }
                    if (relayConfig.Config.Secret.HasValue())
                    {
                        request.Headers.Add(WebhookEventConstants.SecretSignatureHeaderName, CreateContentHmacSignature(request, relayConfig.Config.Secret));
                    }
                    request.Headers.Add(WebhookEventConstants.RequestIdHeaderName, CreateRequestIdentifier());
                    request.Headers.Add(WebhookEventConstants.EventNameHeaderName, eventName);
                };
                return(client);
            }
            catch (Exception ex)
            {
                logger.Error(@"Failed to connect to subscriber: {0}, this URL is not valid".Fmt(relayConfig.Config.Url), ex);
                return(null);
            }
        }
        public SubscriptionDeliveryResult Relay(SubscriptionRelayConfig subscription, WebhookEvent webhookEvent)
        {
            Guard.AgainstNull(() => subscription, subscription);
            Guard.AgainstNull(() => webhookEvent, webhookEvent);

            var serviceClient = CreateServiceClient(subscription, webhookEvent.EventName, Timeout);

            var attempts = 0;

            while (attempts <= Retries)
            {
                attempts++;

                try
                {
                    var url = subscription.Config.Url;
                    logger.InfoFormat("[ServiceStack.Webhooks.Relays.Clients.EventServiceClient] Notifying {0} of webhook event {1}", url, webhookEvent.ToJson());
                    using (var response = serviceClient.Post(url, webhookEvent.Data))
                    {
                        return(CreateDeliveryResult(subscription.SubscriptionId, webhookEvent.Id, response.StatusCode, response.StatusDescription));
                    }
                }
                catch (WebServiceException ex)
                {
                    if (HasNoMoreRetries(attempts) || ex.IsAny400())
                    {
                        logger.Warn("[ServiceStack.Webhooks.Relays.Clients.EventServiceClient] " + Resources.EventServiceClient_FailedDelivery.Fmt(subscription.Config.Url, attempts), ex);
                        return(CreateDeliveryResult(subscription.SubscriptionId, webhookEvent.Id, (HttpStatusCode)ex.StatusCode, ex.StatusDescription));
                    }
                }
                catch (Exception ex)
                {
                    // Timeout (WebException) or other Exception
                    if (HasNoMoreRetries(attempts))
                    {
                        var message = "[ServiceStack.Webhooks.Relays.Clients.EventServiceClient] " + Resources.EventServiceClient_FailedDelivery.Fmt(subscription.Config.Url, attempts);
                        logger.Warn(message, ex);
                        return(CreateDeliveryResult(subscription.SubscriptionId, webhookEvent.Id, HttpStatusCode.ServiceUnavailable, message));
                    }
                }
            }

            return(null);
        }
            public void WhenWrite_ThenPostsEventToSubscribers()
            {
                var config = new SubscriptionRelayConfig();

                subscriptionCache.Setup(sc => sc.GetAll(It.IsAny <string>()))
                .Returns(new List <SubscriptionRelayConfig>
                {
                    config
                });

                sink.Write("aneventname", new Dictionary <string, string> {
                    { "akey", "avalue" }
                });

                subscriptionCache.Verify(sc => sc.GetAll("aneventname"));
                serviceClient.VerifySet(sc => sc.Retries = AppHostEventSink.DefaultServiceClientRetries);
                serviceClient.VerifySet(sc => sc.Timeout = TimeSpan.FromSeconds(AppHostEventSink.DefaultServiceClientTimeoutSeconds));
                serviceClient.Verify(sc => sc.Relay(config, "aneventname", It.Is <Dictionary <string, string> >(dic => dic["akey"] == "avalue")));
            }
        public SubscriptionDeliveryResult Relay(SubscriptionRelayConfig subscription, string eventName, object data)
        {
            Guard.AgainstNull(() => subscription, subscription);
            Guard.AgainstNullOrEmpty(() => eventName, eventName);

            var serviceClient = CreateServiceClient(subscription, eventName, Timeout);

            var attempts = 0;

            while (attempts <= Retries)
            {
                attempts++;

                try
                {
                    using (var response = serviceClient.Post(subscription.Config.Url, data))
                    {
                        return(CreateDeliveryResult(subscription.SubscriptionId, response.StatusCode, response.StatusDescription));
                    }
                }
                catch (WebServiceException ex)
                {
                    if (HasNoMoreRetries(attempts) || ex.IsAny400())
                    {
                        logger.Warn(Resources.EventServiceClient_FailedDelivery.Fmt(subscription.Config.Url, attempts), ex);
                        return(CreateDeliveryResult(subscription.SubscriptionId, (HttpStatusCode)ex.StatusCode, ex.StatusDescription));
                    }
                }
                catch (Exception ex)
                {
                    // Timeout (WebException) or other Exception
                    if (HasNoMoreRetries(attempts))
                    {
                        var message = Resources.EventServiceClient_FailedDelivery.Fmt(subscription.Config.Url, attempts);
                        logger.Warn(message, ex);
                        return(CreateDeliveryResult(subscription.SubscriptionId, HttpStatusCode.ServiceUnavailable, message));
                    }
                }
            }

            return(null);
        }
예제 #8
0
            public void WhenWrite_ThenPostsEventToSubscribers()
            {
                var config = new SubscriptionRelayConfig();

                subscriptionCache.Setup(sc => sc.GetAll(It.IsAny <string>()))
                .Returns(new List <SubscriptionRelayConfig>
                {
                    config
                });
                var whe = new WebhookEvent
                {
                    EventName = "aneventname"
                };

                sink.Write(whe);

                subscriptionCache.Verify(sc => sc.GetAll("aneventname"));
                serviceClient.VerifySet(sc => sc.Retries = AppHostEventSink.DefaultServiceClientRetries);
                serviceClient.VerifySet(sc => sc.Timeout = TimeSpan.FromSeconds(AppHostEventSink.DefaultServiceClientTimeoutSeconds));
                serviceClient.Verify(sc => sc.Relay(config, whe));
            }
            public void WhenGetAllAndCached_ThenReturnsSubscriptions()
            {
                var config      = new SubscriptionRelayConfig();
                var subscribers = new List <SubscriptionRelayConfig>
                {
                    config
                };

                cacheClient.Setup(cc => cc.Get <CachedSubscription>(It.IsAny <string>()))
                .Returns(new CachedSubscription
                {
                    Subscribers = subscribers
                });

                var result = cache.GetAll("aneventname");

                Assert.That(result.Count, Is.EqualTo(1));
                Assert.That(result[0], Is.EqualTo(config));

                cacheClient.Verify(cc => cc.Get <CachedSubscription>(CacheClientEventSubscriptionCache.FormatCacheKey("aneventname")));
                subscriptionService.Verify(ss => ss.Search(It.IsAny <string>()), Times.Never);
                cacheClient.Verify(cc => cc.Set(It.IsAny <string>(), It.IsAny <CachedSubscription>()), Times.Never);
            }
            public void WhenGetAllAndNothingInCache_ThenCachesSubscriptions()
            {
                var config      = new SubscriptionRelayConfig();
                var subscribers = new List <SubscriptionRelayConfig>
                {
                    config
                };

                cacheClient.Setup(cc => cc.Get <CachedSubscription>(It.IsAny <string>()))
                .Returns((CachedSubscription)null);
                subscriptionService.Setup(ss => ss.Search(It.IsAny <string>()))
                .Returns(subscribers);

                var result = cache.GetAll("aneventname");

                Assert.That(result.Count, Is.EqualTo(1));
                Assert.That(result[0], Is.EqualTo(config));

                cacheClient.Verify(cc => cc.Get <CachedSubscription>(CacheClientEventSubscriptionCache.FormatCacheKey("aneventname")));
                subscriptionService.Verify(ss => ss.Search("aneventname"));
                cacheClient.Verify(cc => cc.Set(CacheClientEventSubscriptionCache.FormatCacheKey("aneventname"), It.Is <CachedSubscription>(cs =>
                                                                                                                                            cs.Subscribers == subscribers), TimeSpan.FromSeconds(cache.ExpiryTimeSeconds)));
            }
예제 #11
0
            public void WhenWrite_ThenPostsEventToSubscribersAndUpdatesResults()
            {
                var config = new SubscriptionRelayConfig();

                subscriptionCache.Setup(sc => sc.GetAll(It.IsAny <string>()))
                .Returns(new List <SubscriptionRelayConfig>
                {
                    config
                });
                var data = new Dictionary <string, string> {
                    { "akey", "avalue" }
                };
                var result = new SubscriptionDeliveryResult();

                serviceClient.Setup(sc => sc.Relay(config, "aneventname", data))
                .Returns(result);

                sink.Write("aneventname", data);

                subscriptionService.Verify(ss => ss.UpdateResults(It.Is <List <SubscriptionDeliveryResult> >(results =>
                                                                                                             (results.Count == 1) &&
                                                                                                             (results[0] == result))));
            }
예제 #12
0
            public void WhenWrite_ThenPostsEventToSubscribersAndUpdatesResults()
            {
                var config = new SubscriptionRelayConfig();

                subscriptionCache.Setup(sc => sc.GetAll(It.IsAny <string>()))
                .Returns(new List <SubscriptionRelayConfig>
                {
                    config
                });
                var result = new SubscriptionDeliveryResult();
                var whe    = new WebhookEvent
                {
                    EventName = "aneventname"
                };

                serviceClient.Setup(sc => sc.Relay(config, whe))
                .Returns(result);

                sink.Write(whe);

                subscriptionService.Verify(ss => ss.UpdateResults(It.Is <List <SubscriptionDeliveryResult> >(results =>
                                                                                                             results.Count == 1 &&
                                                                                                             results[0] == result)));
            }
 private SubscriptionDeliveryResult NotifySubscription(SubscriptionRelayConfig subscription, string eventName, Dictionary <string, string> data)
 {
     ServiceClient.Retries = Retries;
     ServiceClient.Timeout = TimeSpan.FromSeconds(TimeoutSecs);
     return(ServiceClient.Relay(subscription, eventName, data));
 }
 private SubscriptionDeliveryResult NotifySubscription(SubscriptionRelayConfig subscription, WebhookEvent webhookEvent)
 {
     ServiceClient.Retries = Retries;
     ServiceClient.Timeout = TimeSpan.FromSeconds(TimeoutSecs);
     return(ServiceClient.Relay(subscription, webhookEvent));
 }