public ListenerScanner(IReqResBus messageBus, ILogger logger) { Assert.ArgumentNotNull(messageBus, nameof(messageBus)); _logger = logger ?? messageBus.Logger; _builder = new UntypedListenerBuilder(messageBus); }
/// <summary> /// Setup round-robin distribution rules for Request/Response channels /// </summary> /// <typeparam name="TRequest"></typeparam> /// <typeparam name="TResponse"></typeparam> /// <param name="messageBus"></param> /// <param name="inTopics"></param> /// <param name="outTopics"></param> /// <returns></returns> public static IDisposable SetupRequestDistribution <TRequest, TResponse>(this IReqResBus messageBus, string inTopics, IEnumerable <string> outTopics) { Assert.ArgumentNotNull(messageBus, nameof(messageBus)); var rule = new RoundRobinDistributeRule <TRequest>(outTopics); return(messageBus.RequestRouter.AddRequestRouteRule <TRequest, TResponse>(inTopics, rule)); }
public ListenerBuilder(IReqResBus messageBus, IWorkerPool workerPool) { Assert.ArgumentNotNull(messageBus, nameof(messageBus)); Assert.ArgumentNotNull(workerPool, nameof(workerPool)); _messageBus = messageBus; _workerPool = workerPool; }
public static IRequest <TResponse> Request <TRequest, TResponse>(this IReqResBus messageBus, string topic, TRequest requestPayload) { Assert.ArgumentNotNull(messageBus, nameof(messageBus)); var envelope = messageBus.EnvelopeFactory.Create(topic, requestPayload); return(messageBus.RequestEnvelope <TRequest, TResponse>(envelope)); }
/// <summary> /// Setup rules to route the Request/Response channel by inspecting the contents of the request payload /// </summary> /// <typeparam name="TRequest"></typeparam> /// <typeparam name="TResponse"></typeparam> /// <param name="messageBus"></param> /// <param name="inTopic"></param> /// <param name="getTopic"></param> /// <returns></returns> public static IDisposable SetupRequestByExamination <TRequest, TResponse>(this IReqResBus messageBus, string inTopic, Func <TRequest, string> getTopic) { Assert.ArgumentNotNull(messageBus, nameof(messageBus)); Assert.ArgumentNotNull(getTopic, nameof(getTopic)); var rule = new PayloadExamineRule <TRequest>(getTopic); return(messageBus.RequestRouter.AddRequestRouteRule <TRequest, TResponse>(inTopic, rule)); }
/// <summary> /// Build a listener to handle requests of the given type using common options. /// </summary> /// <typeparam name="TRequest">The type of the request object</typeparam> /// <typeparam name="TResponse">The type of the response object</typeparam> /// <param name="messageBus">The message bus</param> /// <param name="build">The lambda function to build the listener</param> /// <returns>A token representing the subscription whic, when disposed, cancels the subscription</returns> public static IDisposable Listen <TRequest, TResponse>(this IReqResBus messageBus, Action <ITopicListenerBuilder <TRequest, TResponse> > build) { Assert.ArgumentNotNull(messageBus, nameof(messageBus)); var builder = new ListenerBuilder <TRequest, TResponse>(messageBus, messageBus.WorkerPool); build(builder); var listener = builder.BuildListener(); var token = messageBus.Listen(builder.Topic, listener); return(builder.WrapToken(token)); }
/// <summary> /// Add predicate-based routing rules for Request/Response operations /// </summary> /// <typeparam name="TRequest"></typeparam> /// <typeparam name="TResponse"></typeparam> /// <param name="messageBus"></param> /// <param name="build"></param> /// <returns></returns> public static IDisposable SetupRequestRouting <TRequest, TResponse>(this IReqResBus messageBus, Action <IFilterRouteBuilderSingleInput <TRequest> > build) { Assert.ArgumentNotNull(messageBus, nameof(messageBus)); Assert.ArgumentNotNull(build, nameof(build)); var builder = new FilterRouteBuilder <TRequest>(); build(builder); var router = builder.Build(); return(messageBus.RequestRouter.AddRequestRouteRule <TRequest, TResponse>(builder.InTopics.FirstOrDefault(), router)); }
private static IDisposable BuildListener(IReqResBus messageBus, Func <TRequest, TResponse> func, Action <IThreadListenerBuilder <TRequest, TResponse> > build, string topic) { var token = messageBus.Listen <TRequest, TResponse>(b => { var c = b .WithTopic(topic) .Invoke(func); build?.Invoke(c); }); return(token); }
public WrappedFunction <TRequest, TResponse> WrapFunction(IReqResBus messageBus, Func <TRequest, TResponse> func, Action <IThreadListenerBuilder <TRequest, TResponse> > build) { Assert.ArgumentNotNull(messageBus, nameof(messageBus)); Assert.ArgumentNotNull(func, nameof(func)); var topic = Guid.NewGuid().ToString(); var token = BuildListener(messageBus, func, build, topic); var newFunc = BuildFunction(messageBus, topic); return(new WrappedFunction <TRequest, TResponse>(newFunc, token, topic)); }
/// <summary> /// Make a request for cases where the type of request is not known until runtime. The bus /// attempts to infer the response type from metadata, and performs the request if possible. /// The request type must inherit from <see cref="IRequestWithResponse{TResponse}"/> in order to make /// the necessary type inferences. /// </summary> /// <param name="messageBus">The message bus</param> /// <param name="topic">The name of the channel</param> /// <param name="requestType">The runtime type of the request</param> /// <param name="request">The request object</param> /// <returns>The response object</returns> public static object Request(this IReqResBus messageBus, string topic, Type requestType, object request) { Assert.ArgumentNotNull(messageBus, nameof(messageBus)); var requestInterface = requestType.GetInterfaces().FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IRequestWithResponse <>)); if (requestInterface == null) { return(null); } var factoryMethod = messageBus.EnvelopeFactory.GetType() .GetMethod(nameof(messageBus.EnvelopeFactory.Create)) .MakeGenericMethod(requestType); var envelope = factoryMethod.Invoke(messageBus.EnvelopeFactory, new[] { new [] { topic }, request, null }); var responseType = requestInterface.GetGenericArguments().Single(); var method = messageBus.GetType().GetMethod(nameof(messageBus.RequestEnvelope)).MakeGenericMethod(requestType, responseType); var waiter = (Request)method.Invoke(messageBus, new[] { envelope }); waiter.WaitForResponse(); waiter.ThrowExceptionIfError(); return(waiter.GetResponseObject()); }
private static Func <TRequest, TResponse> BuildFunction(IReqResBus messageBus, string topic) { TResponse NewFunc(TRequest req) => messageBus.RequestWait <TRequest, TResponse>(topic, req); return(NewFunc); }
public static Task <TResponse> RequestAsync <TRequest, TResponse>(this IReqResBus messageBus, TRequest requestPayload) { var request = Request <TRequest, TResponse>(messageBus, requestPayload); return(request.GetResponseAsync()); }
public static TResponse RequestWait <TRequest, TResponse>(this IReqResBus messageBus, TRequest requestPayload) { return(Request <TRequest, TResponse>(messageBus, requestPayload).GetResponseOrWait()); }
/// <summary> /// Make a request of the given type on the default channel /// </summary> /// <typeparam name="TRequest">The type of request object</typeparam> /// <typeparam name="TResponse">The type of response object</typeparam> /// <param name="messageBus">The message bus</param> /// <param name="requestPayload">The request object, which represents the input arguments to the RPC</param> /// <returns>A token representing the subscription which, when disposed, cancels the subscription</returns> public static IRequest <TResponse> Request <TRequest, TResponse>(this IReqResBus messageBus, TRequest requestPayload) { Assert.ArgumentNotNull(messageBus, nameof(messageBus)); return(messageBus.Request <TRequest, TResponse>(string.Empty, requestPayload)); }
public static IDisposable ListenEnvelopeUntyped(this IReqResBus messageBus, Type requestType, Type responseType, string topic, object target, MethodInfo listener, bool useWeakReferences = false) { return(new UntypedListenerBuilder(messageBus).ListenEnvelopeUntyped(requestType, responseType, topic, target, listener, useWeakReferences)); }
public UntypedListenerBuilder(IReqResBus messageBus) { _messageBus = messageBus; }
public static WrappedFunction <TRequest, TResponse> WrapFunction <TRequest, TResponse>(this IReqResBus messageBus, Func <TRequest, TResponse> func, Action <IThreadListenerBuilder <TRequest, TResponse> > build) { return(new RequestFuncWrapper <TRequest, TResponse>().WrapFunction(messageBus, func, build)); }
/// <summary> /// Get a typed request channel to simplify request/response calls /// </summary> /// <typeparam name="TRequest"></typeparam> /// <typeparam name="TResponse"></typeparam> /// <param name="messageBus"></param> /// <returns></returns> public static RequestChannelProxy <TRequest, TResponse> GetRequestChannel <TRequest, TResponse>(this IReqResBus messageBus) { return(new RequestChannelProxy <TRequest, TResponse>(messageBus)); }
public RequestChannelProxy(IReqResBus messageBus) { Assert.ArgumentNotNull(messageBus, nameof(messageBus)); _messageBus = messageBus; }
public static IDisposable AutoWireupListeners(this IReqResBus messageBus, object obj, bool useWeakReferences = false) { var tokens = new ListenerScanner(messageBus, messageBus.Logger).DetectAndWireUpAll(obj, useWeakReferences); return(new DisposableCollection(tokens)); }
public static IDisposable ListenUntyped(this IReqResBus messageBus, Type requestType, Type responseType, string topic, Func <object, object> handle, bool useWeakReferences = false) { return(new UntypedListenerBuilder(messageBus).ListenUntyped(requestType, responseType, topic, handle, useWeakReferences)); }