What is the best way to wire up ReactiveCommand to invoke a webservice - reactiveui

I am some need help understanding the latest recommended approach to wire up and use reactiveui for a WPF project.
In doing research on the internet on reactiveui I came across various (few) posts spanning a long time period during which the library evolved with the unfortunate result that some of these how-to articles now refer to older ways of doing things which are no longer applicable
I am trying to understand the recommended way to wire up commands (usually to invoke web service which returns a DTO) and I’ve found multiple ways mentioned to do it.
My current understanding is that
// this is the first thing to do
MyCommand = ReactiveCommand.Create()
// variations to wire up the delegates / tasks to be invoked
MyCommand.CreateAsyncTask()
MyCommand.CreateAsyncFunc()
MyCommand.CreateAsyncAction()
// this seems to be only way to wire handler for receiving result
MyCommand.Subscribe
// not sure if these below are obsolete?
MyCommand.ExecuteAsync
MyCommand.RegisterAsyncTask()
Could someone try to explain which of these variations is the latest API and which are obsolete, with perhaps a few words about when to use each of them

The changes on the ReactiveCommand API are documented in this blog post:
http://log.paulbetts.org/whats-new-in-reactiveui-6-reactivecommandt/
The first option - ReactiveCommand.Create() - just creates a reactive command.
To define a command which asynchronously returns data from a service you would use :
MyCommand = ReactiveCommand.CreateAsyncTask(
canExec, // optional
async _ => await api.LoadSomeData(...));
You may use the Subscribe method to handle data when it is received:
this.Data = new ReactiveList<SomeDTO>();
MyCommand.Subscribe(items =>
{
this.Data.Clear();
foreach (var item in items)
this.Data.Add(item);
}
Though, the simplest thing is to use instead the ToProperty method like this:
this._data = MyCommand
.Select(items => new ReactiveList<SomeDTO>(items))
.ToProperty(this, x => x.Data);
where you have defined an output property for Data:
private readonly ObservableAsPropertyHelper<ReactiveList<SomeDTO>> _data;
public ReactiveList<SomeDTO> Data
{
get { return _data.Value; }
}

Related

MessagingCentre Does it pass object by value or by reference?

With reference to .Net Maui: How to read/write (get/set) a global object from any content page (MVVM)
I now have a need to pass an object that is rather a large (>500Mb), it is an OpenMap extract, a RouterDb object (Itinero http://docs.itinero.tech/index.html)
Though I am trying to use MVVM some packages (Mapsui) use code behind so I am left with a mixture of ViewModel and Codebehind. I can overcome the limitation of not having any kind of global object reference by using the MessagingCenter which works remarkably well.
I am wondering if this mechanism can handle the passing of large objects (megabytes) or if internally it simply passes a reference to the object. I suspect from my experiments that it is trying to pass a copy of the object and failing, as I end up with a null object.
Here's the code
MessagingMarker.cs - just a placeholder class
namespace RouteIt.Models;
public class MessagingMarker
{
}
In my MainPageViewModel.cs
//Takes about 10seconds to load
using (var stream = new FileInfo(#"C:\Users\Gordon\source\repos\RouteIt\Resources\Raw\gb.routerdb").OpenRead())
{
routerDb = RouterDb.Deserialize(stream);
}
//send message to codebehind containing object or reference?
MessagingCenter.Send(new MessagingMarker(), "RouterDbLoaded", routerDb);
and in my receiving MainPage.xaml.cs constructor
MessagingCenter.Subscribe<MessagingMarker, RouterDb>(this, "RouterDbLoaded", (sender, arg) =>
{
routerDb = arg;
});
router = new(routerDb);
Any thoughts? (And yes perhaps I need to re-struture my app, but at this stage I don't want to really, one day Mapsui might support mvvm apparently.)
As always thanks for at least reading :)

Spring Webflux throws a "block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-2"

I have a small issue with doing a blocking operation in Spring Webflux. I retrieve a list of article documents and from the list of article documents, i would like to update another object.
When i execute the below, sometimes it works and sometimes it throws a "block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-2". Could you please suggest how to fix. I dont really want to make it blocking but not sure how to proceed. There are similar threads in stackoverflow but not with respective to my requirement.
It would be really nice if someone could suggest a way to work around ?
private OrderInfo setPrices(final OrderInfo orderInfo) {
final List<ArticleDocument> articleDocuments = getArticleDocuments(orderInfo).block(); // Problematic line
for (ArticleDocument article : articleDocuments) {
//Update orderInfo based on one of the article price and few more condition.
}
return orderInfo;
}
private Mono<List<ArticleDocument>> getArticleDocuments(final OrderInfo orderInfo) {
return this.articleRepository.findByArticleName(orderInfo.getArticleName()).collectList();
}
It has to be something like this. Please take note that I have not tested it on my IDE. To modify anything please comment and figure it out together.
private Mono<OrderInfo> setPrices(final OrderInfo orderInfo) {
getArticleDocuments(orderInfo)
.map(articleDocuments -> {
articleDocuments.forEach(article -> // UPDATE AS YOU NEED);
return orderInfo;
});
private Mono<List<ArticleDocument>> getArticleDocuments(final OrderInfo orderInfo) {
return this.articleRepository.findByArticleName(orderInfo.getArticleName()).collectList();
}
Remember, you have to put everything under chaining. that's why you have to return Mono<OrderInfo> instead of OrderInfo from setPrices method. If you find my suggested code is tough to adapt to your current coding structure, you can show me the full code. Let's find out we can build a good chain or not.
BTW, you were using getArticleDocuments(orderInfo).block();. See? you were using .block()? Don't do that in a chain. don't ever block anything in a request to the response chain process. you will return mono or flux from the controller and everything will be handled by webflux

AWS Lambda: Handling variable input types

What's the standard means of processing input to an AWS Lambda handler function, when the format of the incoming JSON varies depending on the type of trigger?
e.g. I have a Lambda function that gets called when an object is created in an S3 bucket, or when an hourly scheduled event fires. Obviously, the JSON passed to the handler is formatted differently.
Is it acceptable to overload Lambda handler functions, with the input type defined as S3Event for one signature and ScheduledEvent for the other? If not, are developers simply calling JsonConvert.DeserializeObject in try blocks? Or is the standard practice to establish multiple Lambda functions, one for each input type (yuck!)?
You should use one function per event.
Having multiple triggers for one Lambda will just make things way harder, as you'll end up with a bunch of if/else, switch statements or even Factory methods if you want to apply design patterns.
Now think of Lambda functions as small and maintainable. Think of pieces of code that should do one thing and should do it well. By the moment you start having multiple triggers, you kind of end up with a "Lambda Monolith", as it will have way too many responsibilities. Not only that, you strongly couple your Lambda functions with your events, meaning that once a new trigger is added, your Lambda code should change. This is just not scalable after two or three triggers.
Another drawback is that you are bound to using one language only if you architect it like that. For some use cases, Java may be the best option. But for others, it may be Node JS, Python, Go...
Essentially, your functions should be small enough to be easily maintainable and even rewritten if necessary. There's absolutely nothing wrong with creating one function per event, although, apparently, you strongly disapprove it. Think of every Lambda as a separate Microservice, which scales out independently, has its own CI/CD pipeline and its own suite of tests.
Another thing to consider is if you want to limit your Lambda concurrent executions depending on your trigger type. This would be unachievable via the "One-Lambda-Does-It-All" model.
Stick with one Lambda per trigger and you'll sleep better at night.
This is actually possible by doing the following:
Have the Lambda signature take a Stream rather than the Amazon event type, so we can get the raw JSON message.
Read the JSON contents of the stream as a string.
Deserialize the string to a custom type in order to identify the event source.
Use the event source information to deserialize the JSON a second time to the appropriate type for the event source.
For example:
public async Task FunctionHandler(Stream stream, ILambdaContext context)
{
using var streamReader = new StreamReader(stream);
var json = await streamReader.ReadToEndAsync();
var serializationOptions = new JsonSerializationOptions { PropertyNameCaseInsensitive = true };
var awsEvent = JsonSerializer.Deserialize<AwsEvent>(json, serializationOptions);
var eventSource = awsEvent?.Records.Select(e => e.EventSource).SingleOrDefault();
await (eventSource switch
{
"aws:s3" => HandleAsync(Deserialize<S3Event>(json, serializationOptions), context),
"aws:sqs" => HandleAsync(Deserialize<SQSEvent>(json, serializationOptions), context),
_ => throw new ArgumentOutOfRangeException(nameof (stream), $"Unsupported event source '{eventSource}'."),
});
}
public async Task HandlyAsync(S3Event #event) => ...
public async Task HandleAsync(SQSEvent #event) => ...
public sealed class AwsEvent
{
public List<Record> Records { get; set; }
public sealed class Record
{
public string EventSource { get; set; }
}
}

Get room/rooms of client [duplicate]

I can get room's clients list with this code in socket.io 0.9.
io.sockets.clients(roomName)
How can I do this in socket.io 1.0?
Consider this rather more complete answer linked in a comment above on the question: https://stackoverflow.com/a/24425207/1449799
The clients in a room can be found at
io.nsps[yourNamespace].adapter.rooms[roomName]
This is an associative array with keys that are socket ids. In our case, we wanted to know the number of clients in a room, so we did Object.keys(io.nsps[yourNamespace].adapter.rooms[roomName]).length
In case you haven't seen/used namespaces (like this guy[me]), you can learn about them here http://socket.io/docs/rooms-and-namespaces/ (importantly: the default namespace is '/')
Updated (esp. for #Zettam):
checkout this repo to see this working: https://github.com/thegreatmichael/socket-io-clients
Using #ryan_Hdot link, I made a small temporary function in my code, which avoids maintaining a patch. Here it is :
function getClient(roomId) {
var res = [],
room = io.sockets.adapter.rooms[roomId];
if (room) {
for (var id in room) {
res.push(io.sockets.adapter.nsp.connected[id]);
}
}
return res;
}
If using a namespace :
function getClient (ns, id) {
return io.nsps[ns].adapter.rooms[id]
}
Which I use as a temporary fix for io.sockets.clients(roomId) which becomes findClientsSocketByRoomId(roomId).
EDIT :
Most of the time it is worth considering avoiding using this method if possible.
What I do now is that I usually put a client in it's own room (ie. in a room whose name is it's clientID). I found the code more readable that way, and I don't have to rely on this workaround anymore.
Also, I haven't tested this with a Redis adapter.
If you have to, also see this related question if you are using namespaces.
For those of you using namespaces I made a function too that can handle different namespaces. It's quite the same as the answer of nha.
function get_users_by_room(nsp, room) {
var users = []
for (var id in io.of(nsp).adapter.rooms[room]) {
users.push(io.of(nsp).adapter.nsp.connected[id]);
};
return users;
};
As of at least 1.4.5 nha’s method doesn’t work anymore either, and there is still no public api for getting clients in a room. Here is what works for me.
io.sockets.adapter.rooms[roomId] returns an object that has two properties, sockets, and length. The first is another object that has socketId’s for keys, and boolean’s as the values:
Room {
sockets:
{ '/#vQh0q0gVKgtLGIQGAAAB': true,
'/#p9Z7l6UeYwhBQkdoAAAD': true },
length: 2 }
So my code to get clients looks like this:
var sioRoom = io.sockets.adapter.rooms[roomId];
if( sioRoom ) {
Object.keys(sioRoom.sockets).forEach( function(socketId){
console.log("sioRoom client socket Id: " + socketId );
});
}
You can see this github pull request for discussion on the topic, however, it seems as though that functionality has been stripped from the 1.0 pre release candidate for SocketIO.

How to use dispatcher

how to use dispatcher.BeginInvoke in for loop( httpwebrequest).With each dispatcher.BeginInvoke have complete before call another dispatcher.BeginInvoke. Because objects return by httpwerequest are wrong position.
No, BeginInvoke is asynchronous - you're basically adding delegates to a queue of items to be executed on the UI thread.
If you need to wait until the delegate has executed before you continue work in your background thread, you'll need to do a bit of work yourself, as Silverlight doesn't support the synchronous Dispatcher.Invoke method, or the DispatcherOperation.Wait() method. Silverlight tries to avoid synchronous approaches like this - if you can possibly redesign your code so that you don't need to wait, that would be preferable.
Being able to easily convert a synchronous sequence of operations into asynchrounous code has been a subject I've blogged about a fair bit. If you want to take up my approach you will need to add the following (relatively small) chunks of code:
The core AsyncOperationService
Code to create an AsyncOperation from the .NET Async Pattern
A couple of Extension methods for WebRequest
Here is some example code that has the flavour of what you describe in your question:-
IEnumerable<AsyncOperation> LoadSomeStuff(IList<string> urls)
{
for (string url in urls)
{
yield return AsyncOperationService.SwitchToBackgroundThread();
WebRequest req = WebRequest.Create(url);
WebResponse resp = null;
yield return req.GetResponseAsyncOp(r => resp = r);
using (resp)
{
// Do stuff with the Web Response such as construct model class instances from a stream.
}
// When ready to actually start touching the UI
yield return AsyncOperationService.SwitchToUIThread();
// Do stuff to the UI
}
}
usage:
List<string> urls = new List<string> {"pinkElephants.xml", "whileElephants.xml"}
LoadSomeStuff(urls).Run(err =>
{
if (err == null)
{
// Cool, it all worked and I probably don't need to do anything
}
else
{
// Something bad happened, lets tell the user about it in the UI somehow.
}
});
Note that this isn't the most efficient code possible. However in many cases the time it takes HTTP response to be delivered massively out-weighs the time the rest of the code uses up so the inefficiency can be quite small and well worth the reduced complexity of code.

Resources