-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement and add examples for Adapters and Providers from Infrastructure folder? #57
Comments
For example, If you need to get a user, you can create a port: interface GetUserPort {
getUser(id: string): Promise<User>
} And adapter (repository in this case is an adapter for the database): class UserRepository implements GetUserPort {
async getUser(id: string): Promise<User> {
const user = await this.database.query('SELECT * FROM users WHERE id = $1', [id]);
return user;
} If you need to get a user from an external api, the principle is the same: class UserAdapter implements GetUserPort {
async getUser(id: string): Promise<User> {
const user = await fetch('http://some-external-api.com', { userId: id });
return user;
} In the service where you need to use this adapter you would do something like this: export class UserService {
constructor(
@Inject(UserAdapter) // <- inject adapter
private user: GetUserPort; // <- service itself depends on a port
) {}
async doSomething(id: string) {
const user = await this.user.getUser(id);
// ...
} |
It's ok for external DB or HTTP API, but what about calling other microservices (Kafka, Rabbit)? Because I saw "microservice adapters" part of the diagram. |
Same principles can be applied for any out-of-process communications. Your domain doesn't need to know how your microservices communicate: via HTTP, RabbitMQ, Kafka, etc. Domain doesn't care about that details, it just calls a port to do something, and adapter gets care of that. This is simple abstraction principle. For example, using RabbitMQ RPC class UserAdapter implements GetUserPort {
async getUser(id: string): Promise<User> {
await this.rabbitMQ.sendToQueue('GET_USER', { userId: id }, {
replyTo: queue
});
const user = await channel.consume(queue, /* ... listen for RPC response */)
return user;
} |
@Sairyss thanks, great project! |
What if some part of |
@ErlanBazarov You can combine a call to your db and a call to external service into a single method What you usually should do in that case is create a copy of that data stored in 3rd party service into your own database, storage is cheap nowadays. If data gets updated frequently in the 3rd party storage, you can use periodic jobs to keep it fresh in your db. This way you will not depend that much on a 3rd party. |
Can you provide some useful examples for Adapters? If we integrate with call some 3rd party API we use Adapters?
Providers using as NestJS providers or what?
The text was updated successfully, but these errors were encountered: