async Task SendSubscribeMessageWithRetries(string destination, OutgoingMessage subscriptionMessage, string messageType, ContextBag context, int retriesCount = 0) { var state = context.GetOrCreate <Settings>(); try { var transportOperation = new TransportOperation(subscriptionMessage, new UnicastAddressTag(destination)); var transportTransaction = context.GetOrCreate <TransportTransaction>(); await dispatcher.Dispatch(new TransportOperations(transportOperation), transportTransaction, context).ConfigureAwait(false); } catch (QueueNotFoundException ex) { if (retriesCount < state.MaxRetries) { await Task.Delay(state.RetryDelay).ConfigureAwait(false); await SendSubscribeMessageWithRetries(destination, subscriptionMessage, messageType, context, ++retriesCount).ConfigureAwait(false); } else { var message = $"Failed to subscribe to {messageType} at publisher queue {destination}, reason {ex.Message}"; Logger.Error(message, ex); throw new QueueNotFoundException(destination, message, ex); } } }
public override async Task <IContainSagaData> Find(IServiceProvider builder, SagaFinderDefinition finderDefinition, SynchronizedStorageSession storageSession, ContextBag context, object message, IReadOnlyDictionary <string, string> messageHeaders, CancellationToken cancellationToken = default) { var propertyAccessor = (Func <object, object>)finderDefinition.Properties["property-accessor"]; var propertyValue = propertyAccessor(message); var sagaPropertyName = (string)finderDefinition.Properties["saga-property-name"]; var lookupValues = context.GetOrCreate <SagaLookupValues>(); lookupValues.Add <TSagaData>(sagaPropertyName, propertyValue); if (propertyValue == null) { var saga = context.Get <ActiveSagaInstance>(); var sagaEntityName = saga.Metadata.Name; var messageName = finderDefinition.MessageTypeName; throw new Exception($"Message {messageName} mapped to saga {sagaEntityName} has attempted to assign null to the correlation property {sagaPropertyName}. Correlation properties cannot be assigned null."); } if (sagaPropertyName.ToLower() == "id") { return(await sagaPersister.Get <TSagaData>((Guid)propertyValue, storageSession, context, cancellationToken).ConfigureAwait(false)); } return(await sagaPersister.Get <TSagaData>(sagaPropertyName, propertyValue, storageSession, context, cancellationToken).ConfigureAwait(false)); }
async Task <CompletableSynchronizedStorageSession> OpenSession(ContextBag context) { var transportTransaction = context.GetOrCreate <TransportTransaction>(); var session = await transportTransactionAdapter.TryAdapt(transportTransaction, context).ConfigureAwait(false) ?? await synchronizedStorage.OpenSession(context).ConfigureAwait(false); return(session); }
public override async Task <IContainSagaData> Find(IServiceProvider builder, SagaFinderDefinition finderDefinition, SynchronizedStorageSession storageSession, ContextBag context, object message, IReadOnlyDictionary <string, string> messageHeaders, CancellationToken cancellationToken) { var headerName = (string)finderDefinition.Properties["message-header-name"]; if (!messageHeaders.TryGetValue(headerName, out var messageHeaderValue)) { var saga = context.Get <ActiveSagaInstance>(); var sagaEntityName = saga.Metadata.Name; var messageName = finderDefinition.MessageTypeName; throw new Exception($"Message {messageName} mapped to saga {sagaEntityName} is missing a header used for correlation: {headerName}."); } var correlationPropertyName = (string)finderDefinition.Properties["saga-property-name"]; var correlationPropertyType = (Type)finderDefinition.Properties["saga-property-type"]; object convertedHeaderValue; try { convertedHeaderValue = TypeDescriptor.GetConverter(correlationPropertyType).ConvertFromInvariantString(messageHeaderValue); } catch (Exception exception) { var saga = context.Get <ActiveSagaInstance>(); var sagaEntityName = saga.Metadata.Name; var messageName = finderDefinition.MessageTypeName; throw new Exception($"Message {messageName} mapped to saga {sagaEntityName} contains correlation header {headerName} value that cannot be cast to correlation property type {correlationPropertyType}: {messageHeaderValue}", exception); } var lookupValues = context.GetOrCreate <SagaLookupValues>(); lookupValues.Add <TSagaData>(correlationPropertyName, convertedHeaderValue); if (convertedHeaderValue == null) { var saga = context.Get <ActiveSagaInstance>(); var sagaEntityName = saga.Metadata.Name; var messageName = finderDefinition.MessageTypeName; throw new Exception($"Message {messageName} mapped to saga {sagaEntityName} has attempted to assign null to the correlation property {correlationPropertyName}. Correlation properties cannot be assigned null."); } if (correlationPropertyName.ToLower() == "id") { return(await persister.Get <TSagaData>((Guid)convertedHeaderValue, storageSession, context, cancellationToken).ConfigureAwait(false)); } return(await persister.Get <TSagaData>(correlationPropertyName, convertedHeaderValue, storageSession, context, cancellationToken).ConfigureAwait(false)); }
static TSagaData Resolve <TSagaData>(byte[] data, ContextBag context) where TSagaData : IContainSagaData { var serializer = new DataContractSerializer(typeof(TSagaData)); using (var ms = new MemoryStream(data)) { var saga = (TSagaData)serializer.ReadObject(ms); context.GetOrCreate <Metadata>().SagaData[saga.Id] = data; return(saga); } }
public override async Task <IContainSagaData> Find(IBuilder builder, SagaFinderDefinition finderDefinition, SynchronizedStorageSession storageSession, ContextBag context, object message) { var propertyAccessor = (Func <object, object>)finderDefinition.Properties["property-accessor"]; var propertyValue = propertyAccessor(message); var sagaPropertyName = (string)finderDefinition.Properties["saga-property-name"]; if (sagaPropertyName.ToLower() == "id") { return(await sagaPersister.Get <TSagaData>((Guid)propertyValue, storageSession, context).ConfigureAwait(false)); } var lookupValues = context.GetOrCreate <SagaLookupValues>(); lookupValues.Add <TSagaData>(sagaPropertyName, propertyValue); return(await sagaPersister.Get <TSagaData>(sagaPropertyName, propertyValue, storageSession, context).ConfigureAwait(false)); }