While using angular HttpClient of angular I got to know that HttpClient post method used cold observable and will make 2 separate calls to post data to the server.And also unless you will not subscribe the post method it will not post data to the server.
Although, Rxjs cold observable says it will hold all the sequence until the the end and fire all when it subscribed.
How it will make 2 separate call to server to post data.
COLD is when your observable creates the producer
// COLD
var cold = new Observable((observer) => {
var producer = new Producer();
// have observer listen to producer here
});
HOT is when your observable closes over the producer
// HOT
var producer = new Producer();
var hot = new Observable((observer) => {
// have observer listen to producer here
});
source: https://medium.com/#benlesh/hot-vs-cold-observables-f8094ed53339
I don't believe that this behavior is caused by the use of observables.
Rather I suspect that the browser is issuing a pre-flight OPTIONS request as a 'handshake' with the server to determine whether the CORS protocol is understood. This precedes the POST request and is possibly why you get 2 calls to the server to post data.
Related
In MassTransit Send and RequestClient will be mapped to exchange or queue, That will be handled by LoadBalanced Consumer.
But for Publish Message, It will be consumed by all the instances that are running and waiting for the Message.
So, In StateMachine, Consumer has to publish the Events, That will make if more than once StateMachine Instance running it will be Picked by both StateMachine and Process will be duplicated? This is what happening at my work. So, We end up running Single StateMachine Instance.
await context.Publish(new
{
context.Message.OrderId,
context.Message.Timestamp,
context.Message.CustomerNumber,
context.Message.PaymentCardNumber,
context.Message.Notes
});
This publishes the events to Saga, if Saga is running in LoadBalancer. Both Instance will be receiving the SameEvent. And Start Processing the Event and changing the Next State.
If this is the Case, How to solve this. Only one StateMachine Should Pick the published message at once.
We end up running Single StateMachine Instance. So, the Published message wont be picked by both instance and will endup haivng duplicate process.
The Current Implmentation:
Have a REST Api - That receives the request to Start the Initial State.
var sendToUri =
new Uri(
$"rabbitMq://{_rabbitMqConfig.Host}/{_rabbitMqConfig.VirtualHost}-{_rabbitMqConfig.WfSagaQueue}");
var endPoint = await bus.GetSendEndpoint(sendToUri);
var req = wfRequest;
await endPoint.Send<IWfExecRequest>(req);
In the StateMachine :
services.AddMassTransit(x =>
{
x.AddConsumer<WfExecRequestConsumer>();
x.AddConsumer<WfTaskCompletedConsumer>();
x.UsingRabbitMq((context, cfg) =>
{
var wfTaskExecHandler = context.GetRequiredService<IWfTaskExecHandler>();
var wfManagementClient = context.GetRequiredService<IWfManagementClient>();
var wfSagaStateMachine = new MsrAutomationStateMachine(wfTaskExecHandler, wfManagementClient);
cfg.Host(HostCredets);
cfg.ReceiveEndpoint(queueName: "msr-automation-wf-exec-request", configureEndpoint: e =>
{
e.PrefetchCount = 1;
e.ConfigureConsumer<WfExecRequestConsumer>(context);
e.StateMachineSaga(wfSagaStateMachine, repo);
});
cfg.ReceiveEndpoint(queueName: "WfTaskCompleted", configureEndpoint: e =>
{
e.PrefetchCount = 1;
e.ConfigureConsumer<WfTaskCompletedConsumer>(context);
});
});
});
This StateMachine Receives , WfExecRequest (Inital Event), TaskCompleted and TaskFaulted (From Muliple Consumer Saga/Consumer) - This was done at Consumer Side as Context.Publish.
So, What I see if we Run more than one Instance of the same StateMachine the TaskCompled Message getting Consumed by both Instances.
Thanks Again.
First, clearly something is wrong with your configuration. If the saga state machine is running on a single queue (receive endpoint, regardless of how many instances of your service are running) it will automatically load balance on that single queue across all running instances.
If you are running multiple instances of the saga state machine on different queues, well yeah, you're basically doing it wrong.
Second, I'm not sure what "LoadBalancer" is but typically something that unnecessary when using a message broker. If "LoadBalancer" is something for your HTTP/API endpoints, that's fine, but the broker and the queue are the scale out points in a message-based system.
If you had posted actual code, or shared some explicit details that would help as it is now it's entirely based on supposition.
How to connect an endpoint(exchange-exchange-queue) in masstransit, accumulate data in the queue, and then, after some time, connect a consumer to this endpoint?
I wanted to do something like:
Task.Run(async () =>
{
for (var i = 0;; i++)
{
await _bus.Publish(new Event(i), stoppingToken);
await Task.Delay(1_000, stoppingToken);
}
});
// a command comes to connect the consumer
var endpoint = _bus.ConnectReceiveEndpoint();
await endpoint.Ready;
// I prepare the consumer, as soon as it is ready, I connect it,
then I read the data that has accumulated during the preparation
(my consumer needs to load the state before reading the data,
and also cannot skip the data during its preparation)
endpoint.ReceiveEndpoint.ConnectConsumer(() =>
_serviceProvider.GetRequiredService<EventConsumer>());
but this code will not create an exchange-exchange relationship, so the queue will be empty
If the exchange bindings (wired to the receive endpoint, which ultimately is a queue) do not exist when messages are published, they are discarded by RabbitMQ.
You would need to connect the receive endpoint in advance, so that the messages end up in the queue.
I'm new to vert.x. Here is what I want to accomplish:
firstly, I have an endpoint handling client app's restful request.
router.post("/clientrequest").handler(routingContext -> {
// This handler will be called for every request
HttpServerResponse response = routingContext.response();
HttpServerRequest request = routingContext.request();
request.handler(buffer->{
// This handler will be called for every chunk of my post request with multi-parts
//
//client is a HttpClient = vertx.createHttpClient()
client.websocket("/anotherWebsockReq",ws->{
//here I get ws as my websocket client instance ws.writeFrame......
});
});
My question is how can I get a websocket instance to send the remaining buffer without creating a new one in the request. handler loop.
Get the websocket before handling buffers:
router.post("/clientrequest").handler(routingContext -> {
// This handler will be called for every request
HttpServerResponse response = routingContext.response();
HttpServerRequest request = routingContext.request();
request.pause()
client.websocket("/anotherWebsockReq",ws->{
request.handler(buffer->{
// write your frames here
}
request.resume();
}
});
Note the call to pause and resume. This is needed because data my lost otherwise.
I was wondering if there is a way to raise events on new subscription to a publisher socket
For example:
PublisherSocket publisher = new PublisherSocket();
publisher.Bind("tcp://*:5555");
NetMQPoller poller = new NetMQPoller { publisher };
poller.RunAsync();
poller.OnSubscription += topic =>
{
AddToPool(topic);
};
Task.Factory.StartNew(() =>
{
SubscriberSocket sub = new SubscriberSocket();
sub.Connect("tcp://127.0.0.1:5555");
Thread.Sleep(1000);
sub.Subscribe("A");
}, TaskCreationOptions.LongRunning);
publisher.ReceiveReady += Publisher_ReceiveReady;
Of course, OnSubscription doesn't really exist, but I was wondering if there is any way around it.
I need my server to be aware of all the subscriptions.
I though about two ways to implement it:
Create an additional router socket in the server, all subscriptions will be sent both to the publisher socket and to the router socket (unsubscriptions as well). This will allow me to poll the subscriptions from the router.
Not use publisher/subscriber at all, create all the pubsub mechanism with router/dealer.
What would you suggest me do?
If you use an XPUB rather than PUB socket you can receive the subscription messages as you would regular messages on any other socket type.
I'm using Node.js and I want to send back multiple responses to the client. So the client will send an AJAX POST request and get back some data. But the server has to continue to do some processing and when that's done, I want it to send more data back.
I know this is a good candidate for Socket.io, but I haven't really seen an example of how to use socket.io in the context of an MVC framework. Does it go in the controller?
You could use Server Sent Events.
Here's an example:
https://github.com/chovy/nodejs-stream (full source code example)
UI
var source = new EventSource('stream');
source.addEventListener('a_server_sent_event', function(e) {
var data = JSON.parse(e.data);
//do something with data
});
Node
if ( uri == '/stream' ) {
//setup http server response handling and get some data from another service
http.get(options, function(resp){
resp.on('data', function(chunk){
res.write("event: a_server_sent_event\n");
res.write("data: "+chunk.toString()+"\n\n");
});
});
}