laravel - what's the proper way to deal with calls towards multiple 3rd party APIs? - laravel-7

I have an app developed using laravel 7. This app gathers data from 3 different 3rd party APIs: api A, B and C. But now i'm stuck.
In the end all this APIs will insert/update data in the same table (inventory) but in the process API A needs a token and the other two are free(no authorization/token needed). For API A i'm storing the token in a table api_a.
Now the question is: should i have 3 different controllers (one for each API) and two models, one for inventory and one for api_a? But that would look ugly for some reason. Or is there a certain pattern that i should look into in order to solve this?
How should i deal with working with multiple 3rd party APIs ?

Related

Where should calculations be done in a MEAN stack app

I am building an ecommerce website for a project for my portfolio, and I wanted to know where the calculations should be done for the cart.
Normally I use react and I create a model folder, route folder and a controller folder but the way I was taught Angular it seems like the services acts like the routes and the actual calls to the database are done in the node server file which I am sure I could separate into a separate controller file. My question is where should the calculations for the cart be done before I send the order to the database? I thought about doing it in the cart component before the order is place or should it be done in the services or in the backend in the controller? I am just trying to figure out what is the standard
When writing an Angular app, I think it is important to adhere to the following principles that:
Components - should have a single responsibility for simple view logic only, shouldn't reach out to the server, and shouldn't do complex calculations and/or logic that is not related to the view.
Services - should have a single responsibility for (reusable/shared) and complex logic, to do outbound communication and reach out to the server, and to act as data stores (using BehaviorSubjects).
Therefore, if your calculations are needed to update the view of the cart, I would vote that these calculations need to be made at the component. If your calculations are needed to update the items or the request to be sent to the server, they need to be made at the service.
Remember, the component "shouldn't know" how the data comes to it or how it is manipulated or sent to the server. The component should only know, given any data - how to present it in the view, and shouldn't "worry about" how that data came to it. Similarly, the component shouldn't know how the data is calculated before being sent to the server, and this would fall within the responsibility of the service that works with and processes the cart data and builds the request to the server.
However, you have to always consider the security of your app, and if a malicious data modification at the client side can affect your cart. If such caculations affect the app's security - they should at least be validated at the server if not fully delegated to it.
I don't know the calculation you need exactly, but since it is an e-commerce website I assume it is simple math such as the total payment amount of checkout.
The main role of the server is communicating to the database. If a task does not involve interacting with data, you can do the calculations on the client-side. Leaving details on client-side allows you to have access to details of your formula, and reduce the communication time between client and server.

Call some different restful services from front-end

Imagine I have an angular project as a front-end which communicates with some other projects which are restful services.
In some pages I need to fetch some data from different restful services,
Is that okay to request any restful service individually in angular?
Or call one restful service which itself call other restful services in back-end?
Or I have to call one restful service but add other entities to this DbContext which I need here just to query?
It depends on what you're doing, but I would say mostly it's OK to do this. This is an established microservices pattern called "Composite UI". See this for details: https://learn.microsoft.com/en-us/dotnet/standard/microservices-architecture/architect-microservice-container-applications/microservice-based-composite-ui-shape-layout
If your microservices are using the CQRS pattern, (while still not wrong) you may be missing an opportunity to compose a view-specific "view model". However, if you're composing\showing data from multiple domains I would say that it's still better to just call multiple microservices to retrieve the data you need.
The only problem you may be introducing if you're not careful, is introducing projection logic (which is not THAT bad) or business logic (very very bad) in your client code if you're doing any processing on the data you receive in order to display it. Composite UI is meant to server a UI with clearly separated sections.

Multiple endpoints of Microsoft Cognitive Services simultaneously

So I'm writing an app in Node.js which analyses sentiment and extracts key phrases using Microsoft Cognitive services. To do these two separate things, I use two nested POST calls, one starting when the other finishes. However, this seems inefficient. The documentation mentions that, to examine sentiment for example, the URL 'must contain /sentiment', not that it must be the only endpoint for that one call. Perhaps I could do both in one call and save myself Azure budget and execution time?
I have tried /sentiment/keyPhrases, that returns 404. /sentiment/../keyPhrases just does keyPhrases. I cannot think of another way to combine the two endpoints.
Turns out I was mislead by my understanding of the documentation. Endpoints must be called separately, and the answers can be combined in Node afterwards using response = response1.concat(response2);.

Application-side join ORM for Node?

To start: I've tried Loopback. Loopback is nice but does not allow for relations across multiple REST data services, but rather makes a call to the initial data service and passes query parameters that ask it to perform the joined query.
Before I go reinventing the wheel and writing a massive wrapper around Loopback's loopback-rest-connector, I need to find out if there are any existing libraries or frameworks that already tackle this. My extensive Googling has turned up nothing so far.
In a true microservice environment, there is a service per database.
http://microservices.io/patterns/data/database-per-service.html
From this article:
Implementing queries that join data that is now in multiple databases
is challenging. There are various solutions:
Application-side joins - the application performs the join rather than
the database. For example, a service (or the API gateway) could
retrieve a customer and their orders by first retrieving the customer
from the customer service and then querying the order service to
return the customer’s most recent orders.
Command Query Responsibility Segregation (CQRS) - maintain one or more
materialized views that contain data from multiple services. The views
are kept by services that subscribe to events that each services
publishes when it updates its data. For example, the online store
could implement a query that finds customers in a particular region
and their recent orders by maintaining a view that joins customers and
orders. The view is updated by a service that subscribes to customer
and order events.
EXAMPLE:
I have 2 data microservices:
GET /pets - Returns an object like
{
"name":"ugly",
"type":"dog",
"owner":"chris"
}
and on a completely different microservice....
GET /owners/{OWNER_NAME} - Returns the owner info
{
"owner":"chris",
"address":"under a bridge",
"phone":"123-456-7890"
}
And I have an API-level microservice that is going to call these two data services. This is the microservice that I will be applying this at.
I'd like to be able to establish a model for Pet such that, when I query pet, upon a successful response from GET /pets, it will "join" with owners (send a GET /owners/{OWNERS_NAME} for all responses), and to the user, simply return a list of pets that includes their owner's data.
So GET /pets (maybe something like Pets.find()) would return
{
"name":"ugly",
"type":"dog",
"owner": "chris",
"address": "under a bridge",
"phone": "123-456-7890"
}
Applying any model/domain logic on your API-gateway is bad decision, and considered as bad practice. API Gateway should only do your systems's CAS (with relying onto Auth service which holds the logic), And convert incoming external requests into inner system requests (different headers/ requester payload data) and proxy formatted requests to services for any other work, recieves them, cares about encapsulating errors, and presents every response in proper external form.
Another point, if there is alot of joins between two models required for application core flow (validation/scoping etc) then perhaps you should reconsider to which Business Domain your models/services are bound. If it's same BD perhaps they should be together. Priciples of Domain-Driven-Design helped me to understand where real boundaries between micro-services are.
If you work with loopback (like we are and face same problem we faced - that loopback have no proper join implementation) you can have separate Report/Combined data service, which is only one who can access to all the service databases and does it only for READ purposes - i.e. queries. Provide it with separately set-up read-only wide access to the db - instead of having only one datasource being set up (single database) it should be able to read from all the databases which are in scope of this query-join db user.
Such service should able to generate proper joins with expected output schema from configuration json - like loopback models (thats what I did in same case). Once abstraction is done it's pretty simple to build/add any equery with any complex joins. It's clean, and it's easy to reason about. Also, it's DBA friendly. For me such approach worked well so far.

How to simulate fake third party response for testing

Is there a way I can generate fake third API response ?
Why I want to generate fake API response?
Some third API have rete limit of calls. Example twitter.
Testing with original third party API adds network delay.
Testing should not be affected if third party is down.
Generating same response everytime for writing test cases.
Currently we are solving this problem by manually writing code to generate same response for the API. But it is not feasible and expandable. If third party is changing API we need to re-write complete code again and as count of third party is getting increased. It will add lot of time for writing this code.
What type of solution I am looking for ?
Some time of network sniffing or simulator inside which I can run my app for one time and I can save response generated by third party API.
I think, there is just the right tool for you. Look at https://github.com/skrill/holoserve
It's written in Ruby, but runs as a standalone service can fake any http service at the HTTP-level. You can define request/response pairs along with variants of it (e.g. different parameters).
I'm using it to mock wbeservices during the tests.

Resources