Task IPublishEndpointConverter.Publish(IPublishEndpoint endpoint, object message, CancellationToken cancellationToken) { if (endpoint == null) { throw new ArgumentNullException(nameof(endpoint)); } if (message == null) { throw new ArgumentNullException(nameof(message)); } var msg = message as T; if (msg == null) { throw new ArgumentException("Unexpected message type: " + TypeMetadataCache.GetShortName(message.GetType())); } return(endpoint.Publish(msg, cancellationToken)); }
public void Configure(IReceiveEndpointConfigurator configurator, IConfigurationServiceProvider configurationServiceProvider) { ISagaStateMachineFactory stateMachineFactory = configurationServiceProvider.GetRequiredService<ISagaStateMachineFactory>(); SagaStateMachine<TInstance> stateMachine = stateMachineFactory.CreateStateMachine<TInstance>(); var repositoryFactory = configurationServiceProvider.GetRequiredService<ISagaRepositoryFactory>(); ISagaRepository<TInstance> repository = repositoryFactory.CreateSagaRepository<TInstance>(); var stateMachineConfigurator = new StateMachineSagaConfigurator<TInstance>(stateMachine, repository, configurator); LogContext.Debug?.Log("Configuring endpoint {Endpoint}, Saga: {SagaType}, State Machine: {StateMachineType}", configurator.InputAddress.GetLastPart(), TypeMetadataCache<TInstance>.ShortName, TypeMetadataCache.GetShortName(stateMachine.GetType())); GetSagaDefinition(configurationServiceProvider) .Configure(configurator, stateMachineConfigurator); foreach (Action<ISagaConfigurator<TInstance>> action in _configureActions) action(stateMachineConfigurator); configurator.AddEndpointSpecification(stateMachineConfigurator); }
Task IConsumeObserverConverter.PostConsume(IConsumeObserver observer, object context) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } var consumeContext = context as ConsumeContext <T>; if (consumeContext == null) { throw new ArgumentException("Unexpected context type: " + TypeMetadataCache.GetShortName(context.GetType())); } return(observer.PostConsume(consumeContext)); }
/// <summary> /// Send a message /// </summary> /// <param name="provider"></param> /// <param name="message">The message</param> /// <param name="cancellationToken"></param> /// <returns>The task which is completed once the Send is acknowledged by the broker</returns> public static async Task Send(this ISendEndpointProvider provider, object message, CancellationToken cancellationToken = default(CancellationToken)) { if (message == null) { throw new ArgumentNullException(nameof(message)); } var messageType = message.GetType(); Uri destinationAddress; if (!EndpointConvention.TryGetDestinationAddress(message, out destinationAddress)) { throw new ArgumentException($"A convention for the message type {TypeMetadataCache.GetShortName(messageType)} was not found"); } var endpoint = await provider.GetSendEndpoint(destinationAddress).ConfigureAwait(false); await endpoint.Send(message, cancellationToken).ConfigureAwait(false); }
Type CreateTypeFromInterface(ModuleBuilder builder, Type interfaceType) { var typeName = _proxyNamespaceSuffix + "." + (interfaceType.IsNested && interfaceType.DeclaringType != null ? (interfaceType.DeclaringType.Name + '+' + TypeMetadataCache.GetShortName(interfaceType)) : TypeMetadataCache.GetShortName(interfaceType)); try { var typeBuilder = builder.DefineType(typeName, TypeAttributes.Serializable | TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed, typeof(object), new[] { interfaceType }); typeBuilder.DefineDefaultConstructor(MethodAttributes.Public); IEnumerable <PropertyInfo> properties = interfaceType.GetAllProperties(); foreach (var property in properties) { var fieldBuilder = typeBuilder.DefineField("field_" + property.Name, property.PropertyType, FieldAttributes.Private); var propertyBuilder = typeBuilder.DefineProperty(property.Name, property.Attributes | PropertyAttributes.HasDefault, property.PropertyType, null); var getMethod = GetGetMethodBuilder(property, typeBuilder, fieldBuilder); var setMethod = GetSetMethodBuilder(property, typeBuilder, fieldBuilder); propertyBuilder.SetGetMethod(getMethod); propertyBuilder.SetSetMethod(setMethod); } return(typeBuilder.CreateType()); } catch (Exception ex) { string message = $"Exception creating proxy ({typeName}) for {TypeMetadataCache.GetShortName(interfaceType)}"; throw new InvalidOperationException(message, ex); } }
async Task IFilter <ConsumeContext <TMessage> > .Send(ConsumeContext <TMessage> context, IPipe <ConsumeContext <TMessage> > next) { Stopwatch timer = Stopwatch.StartNew(); try { _observer.OnNext(context); await context.NotifyConsumed(timer.Elapsed, TypeMetadataCache.GetShortName(_observer.GetType())).ConfigureAwait(false); await next.Send(context).ConfigureAwait(false); } catch (Exception ex) { await context.NotifyFaulted(timer.Elapsed, TypeMetadataCache.GetShortName(_observer.GetType()), ex).ConfigureAwait(false); _observer.OnError(ex); throw; } }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { Type dataType = objectType.GetClosingArguments(typeof(MessageData <>)).First(); var reference = serializer.Deserialize <MessageDataReference>(reader); if (reference?.Reference == null) { return(Activator.CreateInstance(typeof(EmptyMessageData <>).MakeGenericType(dataType))); } if (dataType == typeof(string)) { return(new DeserializedMessageData <string>(reference.Reference)); } if (dataType == typeof(byte[])) { return(new DeserializedMessageData <byte[]>(reference.Reference)); } throw new MessageDataException("The message data type was unknown: " + TypeMetadataCache.GetShortName(dataType)); }
public void AddConsumer(Type consumerType, Type consumerDefinitionType) { if (TypeMetadataCache.HasSagaInterfaces(consumerType)) { throw new ArgumentException($"{TypeMetadataCache.GetShortName(consumerType)} is a saga, and cannot be registered as a consumer", nameof(consumerType)); } IConsumerRegistration ValueFactory(Type type) { ConsumerRegistrationCache.Register(type, Registrar); return((IConsumerRegistration)Activator.CreateInstance(typeof(ConsumerRegistration <>).MakeGenericType(type))); } _consumers.GetOrAdd(consumerType, ValueFactory); if (consumerDefinitionType != null) { ConsumerDefinitionRegistrationCache.Register(consumerDefinitionType, Registrar); } }
Task ISendEndpointConverter.Send(ISendEndpoint endpoint, object message, IPipe <SendContext> pipe, CancellationToken cancellationToken) { if (endpoint == null) { throw new ArgumentNullException(nameof(endpoint)); } if (message == null) { throw new ArgumentNullException(nameof(message)); } if (pipe == null) { throw new ArgumentNullException(nameof(pipe)); } if (message is T msg) { return(endpoint.Send(msg, pipe, cancellationToken)); } throw new ArgumentException("Unexpected message type: " + TypeMetadataCache.GetShortName(message.GetType())); }
Task IResponseEndpointConverter.Respond(ConsumeContext consumeContext, object message, IPipe <SendContext> pipe) { if (consumeContext == null) { throw new ArgumentNullException(nameof(consumeContext)); } if (message == null) { throw new ArgumentNullException(nameof(message)); } if (pipe == null) { throw new ArgumentNullException(nameof(pipe)); } if (message is T msg) { return(consumeContext.RespondAsync(msg, pipe)); } throw new ArgumentException("Unexpected message type: " + TypeMetadataCache.GetShortName(message.GetType())); }
public async Task <ScheduledMessage> ScheduleSend(IMessageScheduler scheduler, Uri destinationAddress, DateTime scheduledTime, object message, IPipe <SendContext> pipe, CancellationToken cancellationToken = default) { if (scheduler == null) { throw new ArgumentNullException(nameof(scheduler)); } if (message == null) { throw new ArgumentNullException(nameof(message)); } if (pipe == null) { throw new ArgumentNullException(nameof(pipe)); } if (message is T msg) { return(await scheduler.ScheduleSend(destinationAddress, scheduledTime, msg, pipe, cancellationToken).ConfigureAwait(false)); } throw new ArgumentException("Unexpected message type: " + TypeMetadataCache.GetShortName(message.GetType())); }
/// <summary> /// Connect a consumer with a consumer type and object factory method for the consumer (used by containers mostly) /// </summary> /// <param name="configurator"></param> /// <param name="consumerType"></param> /// <param name="consumerFactory"></param> /// <returns></returns> public static void Consumer(this IReceiveEndpointConfigurator configurator, Type consumerType, Func <Type, object> consumerFactory) { if (configurator == null) { throw new ArgumentNullException(nameof(configurator)); } if (consumerType == null) { throw new ArgumentNullException(nameof(consumerType)); } if (consumerFactory == null) { throw new ArgumentNullException(nameof(consumerFactory)); } LogContext.Debug?.Log("Subscribing Consumer: {ConsumerType} (by type, using object consumer factory)", TypeMetadataCache.GetShortName(consumerType)); var configuratorType = typeof(UntypedConsumerConfigurator <>).MakeGenericType(consumerType); var consumerConfigurator = (IReceiveEndpointSpecification)Activator.CreateInstance(configuratorType, consumerFactory, configurator); configurator.AddEndpointSpecification(consumerConfigurator); }
/// <summary> /// Configure the MassTransit Platform with a startup class, which is used to add consumers, /// sagas, activities, etc. as well as customize the bus configuration if necessary. /// </summary> /// <param name="builder"></param> /// <param name="startupTypes">The startup class types</param> /// <returns></returns> public static IWebHostBuilder UseMassTransitStartup(this IWebHostBuilder builder, params Type[] startupTypes) { builder.ConfigureAppConfiguration((hostingContext, config) => { config.AddEnvironmentVariables("MT_"); }); builder.UseSerilog(); builder.ConfigureServices(services => { foreach (var type in startupTypes) { Log.Information("Adding Startup: {StartupType}", TypeMetadataCache.GetShortName(type)); services.AddSingleton(typeof(IPlatformStartup), type); } }); builder.UseStartup <MassTransitStartup>(); return(builder); }
public async Task <ScheduledRecurringMessage> ScheduleRecurringSend(IRecurringMessageScheduler scheduler, Uri destinationAddress, RecurringSchedule schedule, object message, CancellationToken cancellationToken) { if (scheduler == null) { throw new ArgumentNullException(nameof(scheduler)); } if (schedule == null) { throw new ArgumentNullException(nameof(schedule)); } if (message == null) { throw new ArgumentNullException(nameof(message)); } if (message is T msg) { return(await scheduler.ScheduleRecurringSend(destinationAddress, schedule, msg, cancellationToken).ConfigureAwait(false)); } throw new ArgumentException("Unexpected message type: " + TypeMetadataCache.GetShortName(message.GetType())); }
public static IEnumerable <ValidationResult> ValidateConsumer <TConsumer>(this Configurator configurator) where TConsumer : class { if (!typeof(TConsumer).HasInterface <IConsumer>()) { yield return(configurator.Warning("Consumer", $"The consumer class {TypeMetadataCache<TConsumer>.ShortName} does not implement any IConsumer interfaces")); } IEnumerable <ValidationResult> warningForMessages = ConsumerMetadataCache <TConsumer> .ConsumerTypes.Distinct(MessageTypeComparer) .Where(x => !(HasProtectedDefaultConstructor(x.MessageType) || HasSinglePublicConstructor(x.MessageType))) .Select(x => $"The {TypeMetadataCache.GetShortName(x.MessageType)} message should have a public or protected default constructor." + " Without an available constructor, MassTransit will initialize new message instances" + " without calling a constructor, which can lead to unpredictable behavior if the message" + " depends upon logic in the constructor to be executed.") .Select(message => configurator.Warning("Message", message)); foreach (ValidationResult message in warningForMessages) { yield return(message); } }
/// <summary> /// Set the host headers on the SendContext (for error, dead-letter, etc.) /// </summary> /// <param name="headers"></param> /// <param name="exceptionContext"></param> public static void SetExceptionHeaders(this SendHeaders headers, ExceptionReceiveContext exceptionContext) { var exception = exceptionContext.Exception.GetBaseException() ?? exceptionContext.Exception; var exceptionMessage = ExceptionUtil.GetMessage(exception); headers.Set(MessageHeaders.Reason, "fault"); headers.Set(MessageHeaders.FaultExceptionType, TypeMetadataCache.GetShortName(exception.GetType())); headers.Set(MessageHeaders.FaultMessage, exceptionMessage); headers.Set(MessageHeaders.FaultTimestamp, exceptionContext.ExceptionTimestamp.ToString("O")); headers.Set(MessageHeaders.FaultStackTrace, ExceptionUtil.GetStackTrace(exception)); if (exceptionContext.TryGetPayload(out ConsumerFaultInfo info)) { headers.Set(MessageHeaders.FaultConsumerType, info.ConsumerType); headers.Set(MessageHeaders.FaultMessageType, info.MessageType); } if (exceptionContext.TryGetPayload(out RetryContext retryContext) && retryContext.RetryCount > 0) { headers.Set(MessageHeaders.FaultRetryCount, retryContext.RetryCount); } }
public void ConfigureEndpoints <T>(T configurator, IEndpointNameFormatter endpointNameFormatter) where T : IBusFactoryConfigurator { if (configurator == null) { throw new ArgumentNullException(nameof(configurator)); } if (endpointNameFormatter == null) { endpointNameFormatter = new DefaultEndpointNameFormatter(); } var consumersByEndpoint = _consumers.Values .Select(x => x.GetDefinition(_configurationServiceProvider)) .GroupBy(x => x.GetEndpointName(endpointNameFormatter)); var sagasByEndpoint = _sagas.Values .Select(x => x.GetDefinition(_configurationServiceProvider)) .GroupBy(x => x.GetEndpointName(endpointNameFormatter)); var activitiesByExecuteEndpoint = _activities.Values .Select(x => x.GetDefinition(_configurationServiceProvider)) .GroupBy(x => x.GetExecuteEndpointName(endpointNameFormatter)); var executeActivitiesByEndpoint = _executeActivities.Values .Select(x => x.GetDefinition(_configurationServiceProvider)) .GroupBy(x => x.GetExecuteEndpointName(endpointNameFormatter)); var endpointNames = consumersByEndpoint.Select(x => x.Key) .Union(sagasByEndpoint.Select(x => x.Key)) .Union(activitiesByExecuteEndpoint.Select(x => x.Key)) .Union(executeActivitiesByEndpoint.Select(x => x.Key)); var endpoints = from e in endpointNames join c in consumersByEndpoint on e equals c.Key into cs from c in cs.DefaultIfEmpty() join s in sagasByEndpoint on e equals s.Key into ss from s in ss.DefaultIfEmpty() join a in activitiesByExecuteEndpoint on e equals a.Key into aes from a in aes.DefaultIfEmpty() join ea in executeActivitiesByEndpoint on e equals ea.Key into eas from ea in eas.DefaultIfEmpty() select new { Name = e, Consumers = c, Sagas = s, Activities = a, ExecuteActivities = ea }; foreach (var endpoint in endpoints) { if (_log.IsDebugEnabled) { _log.DebugFormat("Configuring receive endpoint: {0}", endpoint.Name); } configurator.ReceiveEndpoint(endpoint.Name, cfg => { if (endpoint.Consumers != null) { foreach (var consumer in endpoint.Consumers) { if (_log.IsDebugEnabled) { _log.DebugFormat("Configuring consumer {0} on {1}", TypeMetadataCache.GetShortName(consumer.ConsumerType), endpoint.Name); } ConfigureConsumer(consumer.ConsumerType, cfg); } } if (endpoint.Sagas != null) { foreach (var saga in endpoint.Sagas) { if (_log.IsDebugEnabled) { _log.DebugFormat("Configuring saga {0} on {1}", TypeMetadataCache.GetShortName(saga.SagaType), endpoint.Name); } ConfigureSaga(saga.SagaType, cfg); } } if (endpoint.Activities != null) { foreach (var activity in endpoint.Activities) { var compensateEndpointName = activity.GetCompensateEndpointName(endpointNameFormatter); configurator.ReceiveEndpoint(compensateEndpointName, compensateEndpointConfigurator => { if (_log.IsDebugEnabled) { _log.DebugFormat("Configuring activity {0} on {1}/{2}", TypeMetadataCache.GetShortName(activity.ActivityType), endpoint.Name, compensateEndpointName); } ConfigureActivity(activity.ActivityType, cfg, compensateEndpointConfigurator); }); } } if (endpoint.ExecuteActivities != null) { foreach (var activity in endpoint.ExecuteActivities) { if (_log.IsDebugEnabled) { _log.DebugFormat("Configuring activity {0} on {1}", TypeMetadataCache.GetShortName(activity.ActivityType), endpoint.Name); } ConfigureExecuteActivity(activity.ActivityType, cfg); } } }); } }
/// <summary> /// Connect a consumer with a consumer type and object factory method for the consumer /// </summary> /// <param name="connector"></param> /// <param name="consumerType"></param> /// <param name="objectFactory"></param> /// <returns></returns> public static ConnectHandle ConnectConsumer(this IConsumePipeConnector connector, Type consumerType, Func <Type, object> objectFactory) { if (connector == null) { throw new ArgumentNullException(nameof(connector)); } if (consumerType == null) { throw new ArgumentNullException(nameof(consumerType)); } if (objectFactory == null) { throw new ArgumentNullException(nameof(objectFactory)); } if (!consumerType.HasInterface <IConsumer>()) { throw new ArgumentException("The consumer type must implement an IConsumer interface"); } LogContext.Debug?.Log("Connecting Consumer: {ConsumerType} (by type, using object consumer factory)", TypeMetadataCache.GetShortName(consumerType)); return(ConsumerConnectorCache.Connect(connector, consumerType, objectFactory)); }
public void AddSaga(Type sagaType, Type sagaDefinitionType) { if (sagaType.HasInterface <SagaStateMachineInstance>()) { throw new ArgumentException($"State machine sagas must be registered using AddSagaStateMachine: {TypeMetadataCache.GetShortName(sagaType)}"); } _sagas.GetOrAdd(sagaType, type => SagaRegistrationCache.CreateRegistration(type, Registrar)); if (sagaDefinitionType != null) { SagaDefinitionRegistrationCache.Register(sagaDefinitionType, Registrar); } }
SchemaTableColumnTrio GetSchemaAndTableNameAndColumnName(IDbContextDependencies dependencies, Type type) { if (TableNames.TryGetValue(type, out var result) && _enableSchemaCaching) { return(result); } #pragma warning disable EF1001 var entityType = dependencies.Model.FindEntityType(type); var schema = entityType.GetSchema(); var tableName = entityType.GetTableName(); var property = entityType.GetProperties().Single(x => x.Name.Equals(nameof(ISaga.CorrelationId), StringComparison.OrdinalIgnoreCase)); var columnName = property.GetColumnName(); if (string.IsNullOrWhiteSpace(tableName)) { throw new MassTransitException($"Unable to determine saga table name: {TypeMetadataCache.GetShortName(type)} (using model metadata)."); } result = new SchemaTableColumnTrio(schema ?? DefaultSchema, tableName, columnName); if (_enableSchemaCaching) { TableNames.TryAdd(type, result); } return(result); }
static Uri GetPublishAddress(IBus bus, Type messageType) { if (bus.Topology.PublishTopology.TryGetPublishAddress(messageType, bus.Address, out var address)) { return(address); } throw new ArgumentException($"The publish address for the specified type was not returned: {TypeMetadataCache.GetShortName(messageType)}"); }
static string FormatMessage(Type sagaType, Guid correlationId, Type messageType, string message) { return($"{TypeMetadataCache.GetShortName(sagaType)}({correlationId}) Saga exception on receipt of {TypeMetadataCache.GetShortName(messageType)}: {message}"); }
static CachedRegistration GetOrAdd(Type activityType) { if (!activityType.HasInterface(typeof(IExecuteActivity <>))) { throw new ArgumentException($"The type is not an execute activity: {TypeMetadataCache.GetShortName(activityType)}", nameof(activityType)); } if (activityType.HasInterface(typeof(ICompensateActivity <>))) { throw new ArgumentException($"The type is an activity, which supports compensation: {TypeMetadataCache.GetShortName(activityType)}", nameof(activityType)); } var argumentType = activityType.GetClosingArguments(typeof(IExecuteActivity <>)).Single(); return(Cached.Instance.GetOrAdd(activityType, _ => (CachedRegistration)Activator.CreateInstance(typeof(CachedRegistration <,>).MakeGenericType(activityType, argumentType)))); }
public override byte[] GetBody() { if (_body != null) { return(_body); } if (TransportMessage is ITextMessage textMessage) { return(_body = Encoding.UTF8.GetBytes(textMessage.Text)); } if (TransportMessage is IBytesMessage bytesMessage) { return(_body = bytesMessage.Content); } throw new ActiveMqTransportException($"The message type is not supported: {TypeMetadataCache.GetShortName(TransportMessage.GetType())}"); }
IReadProperty <T, TProperty> GetReadProperty <TProperty>(string name) { lock (_properties) { if (_properties.TryGetValue(name, out var property)) { return(property as IReadProperty <T, TProperty>); } if (_propertyIndex.TryGetValue(name, out var propertyInfo)) { if (propertyInfo.PropertyType != typeof(TProperty)) { throw new ArgumentException( $"Property type mismatch, {TypeMetadataCache<TProperty>.ShortName} != {TypeMetadataCache.GetShortName(propertyInfo.PropertyType)}"); } var readProperty = new ReadProperty <T, TProperty>(propertyInfo); _properties[name] = readProperty; return(readProperty); } } throw new ArgumentException($"{TypeMetadataCache<T>.ShortName} does not contain the property: {name}", nameof(name)); }
public Type GetGenericInterface(Type type, Type interfaceType) { if (!interfaceType.GetTypeInfo().IsGenericTypeDefinition) { throw new ArgumentException($"The interface must be a generic interface definition: {TypeMetadataCache.GetShortName(interfaceType)}", nameof(interfaceType)); } // our contract states that we will not return generic interface definitions without generic type arguments if (type == interfaceType) { return(null); } if (type.GetTypeInfo().IsGenericType) { if (type.GetGenericTypeDefinition() == interfaceType) { return(type); } } Type[] interfaces = type.GetTypeInfo().ImplementedInterfaces.ToArray(); return(interfaces.Where(t => t.GetTypeInfo().IsGenericType) .FirstOrDefault(t => t.GetGenericTypeDefinition() == interfaceType)); }
public override byte[] GetBody() { if (_body != null) { return(_body); } if (TransportMessage != null) { return(_body = Encoding.UTF8.GetBytes(TransportMessage.Body)); } throw new AmazonSqsTransportException($"The message type is not supported: {TypeMetadataCache.GetShortName(typeof(Message))}"); }
static CachedRegistration GetOrAdd(Type type) { if (!type.HasInterface(typeof(IExecuteActivityDefinition <,>))) { throw new ArgumentException($"The type is not an activity definition: {TypeMetadataCache.GetShortName(type)}", nameof(type)); } var argumentTypes = type.GetClosingArguments(typeof(IExecuteActivityDefinition <,>)).ToArray(); var genericType = typeof(CachedRegistration <, ,>).MakeGenericType(type, argumentTypes[0], argumentTypes[1]); return(Cached.Instance.GetOrAdd(type, _ => (CachedRegistration)Activator.CreateInstance(genericType))); }
public static void RegisterSagaStateMachines(this IContainerRegistrar registrar, params Type[] types) { foreach (var type in types) { if (!type.HasInterface(typeof(SagaStateMachine <>))) { throw new ArgumentException($"The type is not a saga state machine: {TypeMetadataCache.GetShortName(type)}", nameof(types)); } SagaStateMachineRegistrationCache.Register(type, registrar); } }
IReadProperty <T, TProperty> IReadPropertyCache <T> .GetProperty <TProperty>(PropertyInfo propertyInfo) { lock (_properties) { var name = propertyInfo?.Name ?? throw new ArgumentNullException(nameof(propertyInfo)); if (_properties.TryGetValue(name, out var property)) { return(property as IReadProperty <T, TProperty>); } if (propertyInfo.PropertyType != typeof(TProperty)) { throw new ArgumentException( $"Property type mismatch, {TypeMetadataCache<TProperty>.ShortName} != {TypeMetadataCache.GetShortName(propertyInfo.PropertyType)}", nameof(propertyInfo)); } var readProperty = new ReadProperty <T, TProperty>(propertyInfo); _properties[name] = readProperty; return(readProperty); } }