Spring Integration querying multiple api's and aggregating the response - spring-integration

I'm a newbie to Spring Integration and am looking for a few pointers regarding how I could use it as follows:
Let's say I get a request from a client which for example is looking for a price comparison for some widget. On receipt of this request I would like to call out to multiple different company api's to get different prices and aggregate the each response (different response formats) before returning to the client.
I was just wondering which patterns I could use to do this

Looks like your requirements are fully covered with the Scatter-Gather pattern.
Spring Integration provides a particular implementation for you:
It is a compound endpoint, where the goal is to send a message to the recipients and aggregate the results. Quoting the EIP Book, it is a component for scenarios like best quote, when we need to request information from several suppliers and decide which one provides us with the best term for the requested item.

Related

Domain / integration events payload information in DDD CQRS architecture

I have a question about the integration events used in a microservice / CQRS architecture.
The payload of the event can only have references to aggregates or can it have more information?
If only reference ids can be sent, the only viable solution is to bring the rest of the information with some type of call but the origin would have to implement an endpoint and the services would end up more coupled.
ex. when a user is created and the event is raised.
UserCreated {
userId
name
lastname
document
...
}
Is this correct?
If only reference ids can be sent,
Why would only that be allowed? I have worked with a system which was using micro-services, CQRS and DDD(similar like yours) and we did not have such restrictions. Like in most cases it is: "What works best for your application/business domain". Do not follow any rule blindly. This is perfectly fine to put other information in the events Payload as well.
the only viable solution is to bring the rest of the information with
some type of call but the origin would have to implement an endpoint
and the services would end up more coupled.
This is fine in some cases as well but this brings you to the situation to have additional call's after the event has been processed. I would not do this unless you have a really heavy model/models and it would affect your performance. For example if you have an event executed and based on userId you would need to load a collection of related objects/models for some reason. I had one similar case where I had to load a collection of other objects based on some action on user like event UserCreated. Of course in this case you don't want to send all that data in one Event payload. Instead you send only the id of the user and later call a Get api from the other service to get and save that data to your micro-service.
UserCreated
{
userId
name
lastname
document
... }
Is this correct?
Yes this is fine :)
What you could do instead:
Depending of your business scenario you could publish the information with multiple events with Stages and in different States.
Lets say from UI you have some Wizard-like screen with multiple steps of creation. You could publish
event: UserCreatedDraft with some initial data from 1st Wizard page
event: UserPersonalDataCreated with only part of the object related to private data
event: UserPaymentDataCreated with only the payment data created
UserCreatedFinal with the last step
Of this is just an example for some specific scenario which depends on your use case and your Business requirements. This is just to give you an Idea what you could do in some cases.
Summary:
As you can see there are multiple ways how you can work with these kind of systems. Keep in mind that following the rules is good but in some cases you need to do what is the best based on your business scenario and what works for some application might not be the best solution for your. Do what is most efficient for your system. Working with micro-services we need to deal with latency and async operations anyways so saving some performance on other parts of the system is always good.

How do i fetch only internal messages from O365 using Graph API

I wan't to fetch only messages that are only internal to organization.
Right now the way i see is fetch domains first then for each message see if from/sender domain belongs to that message , based on that differentiate.
But this is lengthy process and not a foolproof technique.
Is there any GRAPH API query i can use which readily provides this ?
It does not apear that the REST API queries for Office 365 includes this information directly in the messages. From the Version 2.0 And the Beta this is not included in message output.
However, it looks like you might be able to get it from the REST API via the headers.
Try the following query:
https://graph.microsoft.com/beta/me/messages?$select=internetMessageHeaders&$top=1
This takes top one messages and shows you the email header of the message.
In the header look for X-OriginatorOrg. The value should be the main domain of your organisation.
Alternatively you can look at the X-MS-Exchange-Organization-MessageDirectionalityheader. If the value here is Originating it should come from inside your own organisation.

Track multiple context for the same Bot

We have a bot that will be used by different customers and depending on their database, sector of activity we're gonna have different answers from the bot and inputs from users. Intents etc will be the same for now we don't plan to make a custom bot for each customer.
What would be the best way to separate data per customer within Chatbase?
I'm not sure if we should use
A new API key for each customer (Do we have a limitation then?)
Differentiate them by the platform filter (seems to not be appropriated)
Differentiate them by the version filter (same it would feel a bit weird to me)
Using Custom Event, not sure how though
Example, in Dialogflow we pass the customer name/id as a context parameter.
Thank you for your question. You listed the two workarounds I would suggest, I will detail the pros/cons:
New API Key for each customer: Could become unwieldy to have to change bots everytime you want to look at a different users' metrics. You should also create a general api (bot) where you send all messages in order to get the aggregate metrics. This would mean making two api calls per message.
Differentiate by version filter: This would be the preferred method, however it could lengthen load times for your reports as your number of users grows. The advantage would be that all of your metrics are in one place, and they will be aggregated while only having to send one api call per message.

What's the right way to gather data from different microservices?

I'm having a problem understanding how basic communication between microservices should be made and I haven't been able to find a good solution or standard way to do this in the other questions. Let's use this basic example.
I have an invoice service that return invoices, every invoice will contain information(ids) about the user and the products. If I have a view in which I need to render the invoices for a specific user, I just make a simple request.
let url = "http://my-domain.com/api/v2/invoices"
let params = {userId:1}
request(url,params,(e,r)=>{
const results = r // An array of 1000 invoices for the user 1
});
Now, for this specific view I will need to make another request to get all the details for each product on each invoice.
results.map((invoice)=>{
invoice.items.map((itemId)=>{
const url=`http://my-domain.com/api/v2/products/${itemId}`
request(url,(e,r)=>{
const product = r
//Do something else.....
});
});
});
I know the code example is not perfect but you can see that this will generate a huge number of requests(at least 1000) to the product service and just for 1 user, now imagine if I have 1000 users making this kind of requests.
What is the right way to get the information off all the products without having to make this number of requests in order to avoid performance issues?.
I found some workarounds for this kind of scenarios such as:
Create an API endpoint that accepts a list of IDs in order to make a single request.
Duplicate the information from the Product service within the invoice service and find a way to keep them in sync.
In a microservices architecture are these the right ways to deal with this kind of issues? For me, they look like simple workarounds.
Edit #1: Based on Remus Rusanu response.
As per Remus recommendation, I decided to isolate my services and describe them a little bit better.
As shown in the image above the microservices are now isolated(in specific the Billing-service) and they now are the owners of the data. By using this structure I ensure that Billing-service is able to work even if there are async jobs or even if the other two services are down.
If I need to create a new invoice, I can call the other two microservices(Users, Inventory) synchronously and then update the data on the "cache" tables(Users, Inventory) in my billing service.
Is it also good to assume these "cache" tables are read-only? I assume they are since only the user/inventory services should be able to modify this information to preserve isolation and authority over the information.
You need to isolate the services as so they do not share state/data. The design in your question is a single macroservice split into 3 correlated storage silos. Case in point, you cannot interpret a result form the 'Invoicing' service w/o correlating the data with the 'Products' response(s).
Isolated microservices mean they own their data and they can operate independently. An invoice is complete as returned from the 'Invoices' service. It contains the product names, the customer name, every information on the invoice. All the data came from its own storage. A separate microservice could be 'Inventory', that operates all the product inventories, current stock etc. It would also have its own data, in its own storage. A 'product' can exist in both storage mediums, and there once was logical link between them (when the invoice was created), but the link is severed now. The 'Inventory' microservice can change its products (eg. remove one, add new SKUs etc) w/o affecting the existing Invoices (this is not only a microservice isolation requirement, is also a basic accounting requirement). I'm not going to enter here into details of what is a product 'identity' in real life.
If you find yourself asking questions like you're asking it likely means you do not have microservices. You should think at your microservice boundaries while considering what happens if you replace all communication with async queued based requests (a response can come 6 days later): If the semantics break, the boundary is probably wrong. If the semantics hold, is the right track.
It all depends on the resilience requirements that you have. Do you want your microservice to function when the other microservices are down or not?
The first solution that you presented is the less resilient: if any of the Users or Products microservices goes down, the Invoice microservice would also go down. Is this what you want? On the other hand, this architecture is the simplest. A variation of this architecture is to let the client make the join requests; this leads to a chatty conversation but it has the advantage that the client could replace the missing information with default information when the other microservices are down.
The second solution offers the biggest possible resilience but it's more complex. Having an event-driven architecture helps a lot in this case. In this architecture the microservices act as swimming lanes. A failure in one of the microservices does not propagate to other microservices.

How to provide Detail and Summary objects for my REST api with Node.js and Mongoose?

I want to provide some venue information over my node.js REST API build by mongoose and express.
In my model, I should take care of every details for a venue.
But when requested for summary, I should show only some of them.
And If requested for 1 venue in detail, I should show more.
What is the best way to do it?
If you want to achieve something like this why not create some custom queries for your detail and summary actions?
Basically what you need to do.
Create your custom queries that received the custom data.Do this in your model. (e.g the data for summary or details)
Create specific actions for these speficic type of API calls in your controllers and server it as you wish. (E.g create /getVenueDetail/venueId=213235 )

Resources