Using Request/Reply in SAGA NserviceBus - request

I'm creating a SAGA in NServiceBus. This saga is handling some string which has to be transformed then validated and finally imported. These three actions are separate services. I want the actions as separate handlers in NServiceBus. I'm using the Request/Reply functionality in NServiceBus. Like this:
Bus.Send<TransformRequest>("Backend", m =>
{
m.string = string;
m.MessageId = messageId;
})
.Register(i =>
{
Console.WriteLine("transform finished")
});
The transformationHandler is as follows.
public void Handle(TransformRequest message)
{
var transformationResult = _transformationService.Transform(message.string);
var response = new TransformResponse()
{
string= transformationResult,
messageId = message.messageId,
};
Bus.Reply(response);
}
My question is as follows. When a request is sent to the transformationHandler. A message is sent to the messagequeue. Then hypothetical, the server crashes. The server reboots, the server picks up the TransformationRequest, does it work and wants to do a reply to the Saga, but how? The saga is not alive anymore and can't handle the .Register. How do I handle this problem?
Thank you.

NServiceBus will find the saga instance using a header in the response message automatically for you.
As Sean mentions you need to skip .Register and add a handler for transform result in your saga. The reason is that callbacks using .Register is stored in memory and therefor won't survive a restart

Related

Specifically, how does Reactjs retrieve data from firebase function triggers?

I am using express to create my firebase functions, and I understand how to create regular callable functions. I am lost however on the exact way to implement trigger functions for the background (i.e. onCreate, onDelete, onUpdate, onWrite), as well as how Reactjs in the frontend is supposed to receive the data.
The scenario I have is a generic chat system that uses react, firebase functions with express and realtime database. I am generally confused on the process of using triggers for when someone sends a message, to update another user's frontend data.
I have had a hard time finding a tutorial or documentation on the combination of these questions. Any links or a basic programmatic examples of the life cycle would be wonderful.
The parts I do understand is the way to write a trigger function:
exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
.onWrite((change, context) => {
// Only edit data when it is first created.
if (change.before.exists()) {
return null;
}
// Exit when the data is deleted.
if (!change.after.exists()) {
return null;
}
// Grab the current value of what was written to the Realtime Database.
const original = change.after.val();
console.log('Uppercasing', context.params.pushId, original);
const uppercase = original.toUpperCase();
// You must return a Promise when performing asynchronous tasks inside a Functions such as
// writing to the Firebase Realtime Database.
// Setting an "uppercase" sibling in the Realtime Database returns a Promise.
return change.after.ref.parent.child('uppercase').set(uppercase);
});
But I don't understand how this is being called or how the data from this reaches frontend code.
Background functions cannot return anything to client. They run after a certain event i.e. onWrite() in this case. If you want to update data at /messages/{pushId}/original to other users then you'll have to use Firebase Client SDK to listen to that path:
import { getDatabase, ref, onValue} from "firebase/database";
const db = getDatabase();
const msgRef = ref(db, `/messages/${pushId}/original`);
onValue(msgRef, (snapshot) => {
const data = snapshot.val();
console.log(data)
});
You can also listen to /messages/${pushId} with onChildAdded() to get notified about any new node under that path.

Redux-thunk and redux-promise: empty payload in PENDING state

So I have redux-thunk set up and when I call the updateUser(userInfos) action, it returns a promise to update the server with those infos.
But sequentially I need to update the local state with those infos too, and if I wait for UPDATE_USER_FULFILLED, the effect of my action is not instantaneous, which feels weird for the user.
I thought of reducing the UPDATE_USER_PENDING action to update the local state before the server response arrives with up-to-date data (which should be the same so no re-rendering), but unfortunately, the payload of UPDATE_USER_PENDING action is null :(
Ain't there a way to load it with some data, which would allow instant UI response before server return?
Could be something like:
export function updateUser(user) {
return {
type: UPDATE_USER,
payload: {
promise: userServices.update(user),
localPayload: user,
}
}
}
but I'm guessing this is not available?
For now, the only solution I see is to create a UPDATE_USER_LOCAL action which would do the local action in parallel with the server call. But this is not very elegant and much heavier.
Thanks for the help

Request Deferrer with Service Worker in PWA

I am making a PWA where users can answer the forms. I want it to make also offline, so when a user fills out a form and does not have the internet connection, the reply will be uploaded when he is back online. For this, I want to catch the requests and send them when online. I wanted to base it on the following tutorial:
https://serviceworke.rs/request-deferrer_service-worker_doc.html
I have managed to implement the localStorage and ServiceWorker, but it seems the post messages are not caught correctly.
Here is the core function:
function tryOrFallback(fakeResponse) {
// Return a handler that...
return function(req, res) {
// If offline, enqueue and answer with the fake response.
if (!navigator.onLine) {
console.log('No network availability, enqueuing');
return;
// return enqueue(req).then(function() {
// // As the fake response will be reused but Response objects
// // are one use only, we need to clone it each time we use it.
// return fakeResponse.clone();
// });
}
console.log("LET'S FLUSH");
// If online, flush the queue and answer from network.
console.log('Network available! Flushing queue.');
return flushQueue().then(function() {
return fetch(req);
});
};
}
I use it with:
worker.post("mypath/add", tryOrFallback(new Response(null, {
status: 212,
body: JSON.stringify({
message: "HELLO"
}),
})));
The path is correct. It detects when the actual post event happens. However, I can't access the actual request (the one displayed in try or fallback "req" is basically empty) and the response, when displayed, has the custom status, but does not contain the message (the body is empty). So somehow I can detect when the POST is happening, but I can't get the actual message.
How to fix it?
Thank you in advance,
Grzegorz
Regarding your sample code, the way you're constructing your new Response is incorrect; you're supplying null for the response body. If you change it to the following, you're more likely to see what you're expecting:
new Response(JSON.stringify({message: "HELLO"}), {
status: 212,
});
But, for the use case you describe, I think the best solution would be to use the Background Sync API inside of your service worker. It will automatically take care of retrying your failed POST periodically.
Background Sync is currently only available in Chrome, so if you're concerned about that, or if you would prefer not to write all the code for it by hand, you could use the background sync library provided as part of the Workbox project. It will automatically fall back to explicit retries whenever the real Background Sync API isn't available.

Send RabbitMQ messages to Websocket using Apache Camel

As described in the title I would like to send messages to a Websocket using RabbitMQ. Using AngularJS frontend I want to read the RabbitMQ messages from the Websocket and print them to the console.
In principle my code seems the work, though I can't figure out how to get the actual (string) content of my messages?
Backend:
To create the Websocket and do the routing i am using Spring Boot and Apache Camel: http://camel.apache.org/spring-boot.html.
Routing with Camel is easy and my complete Java Code looks like this:
#Component
public final class CamelRoute extends RouteBuilder {
#Override
public final void configure() throws Exception {
from("rabbitmq:localhost/myExchange")
.to("websocket://myEndpoint?sendToAll=true");
}
}
Running the SpringBoot application works without errors and the logs look good:
Route: route1 started and consuming from: rabbitmq://localhost/myExchange
RabbitMQ:
RabbitMQ runs on my localhost. When I go to http://localhost:15672/ I can see that SpringBoot created the myExchange and I can send messages to it using Publish Message in the UI.
For instance I specify "HelloWorld!" as Payload (without any headers etc.) and click on send.
Frontend:
To read messages from the websocket I basically do the following in my AngularJS controller:
var socket = {
start: function () {
var location = "ws://localhost:9292/myEndpoint";
this._ws = new WebSocket(location);
this._ws.onmessage = this._onmessage;
this._ws.onclose = this._onclose;
},
_onmessage: function (m) {
//Log received RabbitMQ messages from the Websocket
console.log(m);
},
_onclose: function (m) {
if (this._ws) {
this._ws.close();
}
}
};
Receiving the messages seems to work in principle.
When I go to my webpage (localhost:8080/) and open the console in Chrome, it prints a "MessageEvent" object with many properties.
None of these properties though seem tocontain the actual message string, i.e.: "HelloWorld!"?
Update:
Instead of using RabbitMQ to deliver messages, I tried doing the same with Apache Kafka instead, and it worked. Here is what I did:
To test I simply setup a Topic called "test" on a local Kafka Broker using a docker-image.
My route config now looks like this:
from("kafka:localhost:9092?topic=test&groupId=camelgroupid&autoOffsetReset=earliest&consumersCount=1")
.to("websocket://dashboard?sendToAll=true");
To send messages I use the official kafka clients library.
Using the same JS code as posted above, I can now see the messages in the MessageObject.data.
I still wonder why the same approach doesn't work with RabbitMQ? Anyone has an idea?
Finally solved my problem.
The problem was at the client-side. RabbitMQ sends messages via byte[]. The byte[] needs to be decoded correctly when reading the the message from the Websocket.
Here is my updated and working client code:
var socket = {
start: function () {
var location = "ws://localhost:9292/myEndpoint";
this._ws = new WebSocket(location);
// RabbitMQ transmits a byte[], therefore we need to change the binary type:
this._ws.binaryType = 'arraybuffer';
this._ws.onmessage = this._onmessage;
this._ws.onclose = this._onclose;
},
_onmessage: function (m) {
// Decode the byte[]:
var messageString = new TextDecoder('UTF-8').decode(m.data);
console.log(messageString);
},
_onclose: function (m) {
if (this._ws) {
this._ws.close();
}
}
};

Good Async pattern for sequential WebClient requests

Most of the code I've written in .NET to make REST calls have been synchronous. Since Silverlight on Windows Phone only supports Async WebClient and HttpWebRequest calls, I was wondering what a good async pattern is for a Class that exposes methods that make REST calls.
For example, I have an app that needs to do the following.
Login and get token
Using token from #1, get a list of albums
Using token from #1 get a list of categories
etc
my class exposes a few methods:
Login()
GetAlbums()
GetCategories()
since each method needs to call WebClient using Async calls what I need to do is essentially block calling Login till it returns so that I can call GetAlbums().
What is a good way to go about this in my class that exposes those methods?
You might take a look at the Reactive (Rx) framework extensions:
http://www.leading-edge-dev.de/?p=501
http://themechanicalbride.blogspot.com/2009/07/introducing-rx-linq-to-events.html
[edit: ooh - found a good link:]
http://rxwiki.wikidot.com/101samples
They provide a way to "sequence" events, acting only upon certain conditions met - for example, say you had a method "AuthenticationResult Authenticate(string user, string pass)"
You could do something like:
var foo = Observable.FromAsyncPattern<string, string, AuthenticationResult>
(client.BeginAuthenticate, client.EndAuthenticate);
var bar = foo("username","password");
var result = bar.First();
Effectively turning an asynchronous method to a synchronous one. You can extend this to include "chaining":
var bar = foo("username", "password")
.Then(authresult => DoSomethingWithResult(authresult));
Neat stuff. :)
It really depends on what you want to do with this information. If for instance you are attempting to display the list of albums/categories etc, one way to model this would be to
Have one or more classes which implements the INotifyPropertyChanged interface, and are used as data sources for your views (look at the files under the Models folder in a new PhoneListApplication for an example)
Start an async operation to login and get the token, have the async method's callback store the token for you and call a function which will start an async operation to get list of albums and categories.
The callback for the async operation to get a list of albums/categories can update an ObservableList (by adding items to it). I'd imaging you have one class each for albums and categories, each with an observable list. Anyways, once you are done adding, just call NotifyPropertyChanged with the name of the property you changed, and your data should show up.
There is an obvious problem with cases where you want to wait and not proceed until you receive something back over the network (for instance if you want to keep the login page around until you know that you have successfully authenticated). In this case you could just change the page in the async callback.
You could obviously also do something fancier and have a thread wait for an event set by the async callback. I recommend not have the UI thread do this, since it limits your ability to have things like timeouts, and is generally very messy.
We wrote our client-side service layer with all async function signatures that look like this:
public void MyFunction(
ArtType arg,
Action<ReturnType> success,
Action<FailureType> failure);
The service code does an async call to the web service, and when that returns it calls the success callback if the call was successful, and the failure callback if there was a fault/exception. Then the calling code kinda looks like this:
MyServiceInstance.MyFunction(
blahVar,
returnVal => UIInvoker.Invoke(() =>
{
//some success code here
}),
fault => UIInvoker.Invoke(() =>
{
//some fault handling code here
}));
(UIInvoker is just a utility that dispatches back to the UI from a background thread.)
I put something together that is a bit more fluent.
Restful-Silverlight is a library I've created to help with both Silverlight and WP7.
I have included code below to show how you can use the library to retrieve tweets from Twitter.
Sample Usage of Restful-Silverlight retrieving tweets from Twitter:
//silverlight 4 usage
List<string> tweets = new List<string>();
var baseUri = "http://search.twitter.com/";
//new up asyncdelegation
var restFacilitator = new RestFacilitator();
var restService = new RestService(restFacilitator, baseUri);
var asyncDelegation = new AsyncDelegation(restFacilitator, restService, baseUri);
//tell async delegation to perform an HTTP/GET against a URI and return a dynamic type
asyncDelegation.Get<dynamic>(new { url = "search.json", q = "#haiku" })
//when the HTTP/GET is performed, execute the following lambda against the result set.
.WhenFinished(
result =>
{
textBlockTweets.Text = "";
//the json object returned by twitter contains a enumerable collection called results
tweets = (result.results as IEnumerable).Select(s => s.text as string).ToList();
foreach (string tweet in tweets)
{
textBlockTweets.Text +=
HttpUtility.HtmlDecode(tweet) +
Environment.NewLine +
Environment.NewLine;
}
});
asyncDelegation.Go();
//wp7 usage
var baseUri = "http://search.twitter.com/";
var restFacilitator = new RestFacilitator();
var restService = new RestService(restFacilitator, baseUri);
var asyncDelegation = new AsyncDelegation(restFacilitator, restService, baseUri);
asyncDelegation.Get<Dictionary<string, object>>(new { url = "search.json", q = "#haiku" })
.WhenFinished(
result =>
{
List<string> tweets = new List();
textBlockTweets.Text = "";
foreach (var tweetObject in result["results"].ToDictionaryArray())
{
textBlockTweets.Text +=
HttpUtility.HtmlDecode(tweetObject["text"].ToString()) +
Environment.NewLine +
Environment.NewLine;
}
});
asyncDelegation.Go();

Resources