/// <summary> /// Checks for catch up subscriptions. /// </summary> /// <returns></returns> private async Task CheckForCatchUpSubscriptions() { try { Logger.LogInformation("Checking for CatchUp subscriptions"); // Get a handle to the repository INewConfigurationRepository configRepository = this.RepositoryResolver(); // Get the event store server id from the config Guid eventStoreServerId = this.ServiceSettings.Value.EventStoreServerId; // Get the subscription CatchupSubscriptionConfiguration catchUpSubscriptionGroup = await configRepository.GetNextCatchupSubscriptionConfiguration(eventStoreServerId, CancellationToken.None); if (catchUpSubscriptionGroup != null) { Logger.LogInformation($"About connect to stream for catch up {catchUpSubscriptionGroup.StreamName}"); Logger.LogInformation($"CatchUp retrieved with Id {catchUpSubscriptionGroup.SubscriptionId}"); // Create a new subscription ISubscription subscription = this.SubscriptionResolver(); // Start this subscription await subscription.StartSubscription(catchUpSubscriptionGroup.SubscriptionId, catchUpSubscriptionGroup.StreamName, catchUpSubscriptionGroup.Name, catchUpSubscriptionGroup.Position, catchUpSubscriptionGroup.EndPointUri, subscriptionType : SubscriptionType.CatchUp); } } catch (Exception ex) { Logger.LogError(ex); } }
/// <summary> /// Gets the next catchup subscription configuration. /// </summary> /// <param name="eventStoreServerId">The event store server identifier.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns></returns> public async Task <CatchupSubscriptionConfiguration> GetNextCatchupSubscriptionConfiguration(Guid eventStoreServerId, CancellationToken cancellationToken) { CatchupSubscriptionConfiguration result = null; using (SubscriptionServiceConfigurationContext context = this.ContextResolver()) { // Find the next subscription based on Create date (only 1 is returned to simplify processing) Database.Models.CatchupSubscriptionConfiguration nextCatchUpSubscription = await context .CatchupSubscriptionConfigurations .Where(c => c.EventStoreServerId == eventStoreServerId) .OrderBy(c => c.CreateDateTime).FirstOrDefaultAsync(cancellationToken); // Check if we have found a subscription to process if (nextCatchUpSubscription != null) { result = new CatchupSubscriptionConfiguration { Name = nextCatchUpSubscription.Name, SubscriptionId = nextCatchUpSubscription.SubscriptionId, EventStoreServerId = nextCatchUpSubscription.EventStoreServerId, Position = nextCatchUpSubscription.Position, StreamName = nextCatchUpSubscription.StreamName, EndPointUri = nextCatchUpSubscription.EndPointUri, CreateDateTime = nextCatchUpSubscription.CreateDateTime }; } } return(result); }
public async Task <CatchupSubscriptionConfiguration> GetCatchupSubscriptionConfiguration(Guid subscriptionId, CancellationToken cancellationToken) { CatchupSubscriptionConfiguration result = new CatchupSubscriptionConfiguration(); using (SubscriptionServiceConfigurationContext context = this.ContextResolver()) { Database.Models.CatchupSubscriptionConfiguration catchupSubscriptionConfiguration = await context.CatchupSubscriptionConfigurations.Where(s => s.SubscriptionId == subscriptionId).SingleOrDefaultAsync(cancellationToken); result = new CatchupSubscriptionConfiguration { EventStoreServerId = catchupSubscriptionConfiguration.EventStoreServerId, EndPointUri = catchupSubscriptionConfiguration.EndPointUri, Name = catchupSubscriptionConfiguration.Name, StreamName = catchupSubscriptionConfiguration.StreamName, Position = catchupSubscriptionConfiguration.Position, SubscriptionId = catchupSubscriptionConfiguration.SubscriptionId, CreateDateTime = catchupSubscriptionConfiguration.CreateDateTime }; } return(result); }
/// <summary> /// Events the appeared. /// </summary> /// <param name="subscription">The subscription.</param> /// <returns></returns> /// <exception cref="NotFoundException">No Endpoint Uri found for Subscription Id {subscription.SubscriptionGroupId}</exception> /// <exception cref="Exception"></exception> /// <exception cref="InvalidOperationException"></exception> /// <exception cref="TimeoutException">Error processing Event Id {subscription.EventId}. Attempted to Send to Uri: {endpoint}, request Timed out</exception> private async Task <Boolean> EventAppeared(SubscriptionDataTransferObject subscription) { Boolean result = false; String endpoint = null; try { // Lookup the endpoint that we need to post this event to // Get the config repository INewConfigurationRepository repository = this.ConfigurationRepositoryResolver(); // Get the endpoint from the repository if (this.Type == SubscriptionType.Persistent) { SubscriptionConfiguration configuration = await repository.GetSubscriptionConfiguration(Guid.Parse(subscription.SubscriptionGroupId), CancellationToken.None); endpoint = configuration.EndPointUri; } else if (this.Type == SubscriptionType.CatchUp) { CatchupSubscriptionConfiguration configuration = await repository.GetCatchupSubscriptionConfiguration(Guid.Parse(subscription.SubscriptionGroupId), CancellationToken.None); endpoint = configuration.EndPointUri; } // Check we have found an endpoint if (string.IsNullOrEmpty(endpoint)) { throw new NotFoundException($"No Endpoint Uri found for Subscription Id {subscription.SubscriptionGroupId}"); } // Send the request to the endpoint using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, endpoint)) { request.Content = new StringContent(subscription.SerialisedData, Encoding.UTF8, "application/json"); // Set the http timeout from the config value CancellationTokenSource cts = new CancellationTokenSource(); cts.CancelAfter(100000); HttpResponseMessage response = await this.HttpClient.SendAsync(request, cts.Token); if (!response.IsSuccessStatusCode && response.StatusCode != HttpStatusCode.InternalServerError) { // Get the message contents String responseBody = await response.Content.ReadAsStringAsync(); // Construct an error message String errorMessage = $"Failed Posting to Subscription Group Endpoint [{response.StatusCode}]. Response [{responseBody}]"; throw new Exception(errorMessage); } if (!response.IsSuccessStatusCode && response.StatusCode == HttpStatusCode.InternalServerError) { String errorMessage = "Failed Posting to Subscription Group Endpoint - Internal Server Error"; throw new InvalidOperationException(errorMessage); } } result = true; } catch (TaskCanceledException tcex) { // This transaction has timed out throw new TimeoutException($"Error processing Event Id {subscription.EventId}. Attempted to Send to Uri: {endpoint}, request Timed out"); } catch (NotFoundException nex) { Logger.LogError(nex); } catch (Exception ex) { String errorMessage = $"Error processing Event Id {subscription.EventId}. Attempted to Send to Uri: {endpoint}"; Exception exception = new Exception(errorMessage, ex); Logger.LogError(exception); } return(result); }