Объяснение индивидуальной транспортной стратегии

Встроенные протоколы

NestJS имеет встроенную поддержку нескольких протоколов для использования в качестве транспортного уровня для контроллеров. Другими словами, что касается микросервисов - он имеет встроенную поддержку таких вещей, как AMQP, gRPC, MQTT (и многое другое).

Однако если вы хотите, чтобы ваш микросервис принимал сообщения из неподдерживаемого протокола (например, AWS SQS или GCP PubSub), вам не повезло. В настоящее время для этого нет встроенной поддержки (хотя они работают над добавлением дополнительных протоколов - так что это может быть добавлено в будущем).

Стратегия настраиваемого транспортного уровня

Хорошо, тебе не совсем повезло.

На жаргоне NestJS коммуникационный протокол, который микросервис будет использовать для получения сообщений, называется стратегией транспортного уровня.

И, к счастью, NestJS позволяет нам определять нашу собственную стратегию при создании нового микросервиса.

Итак, что же такое стратегия?
Проще говоря - это экземпляр класса, который расширяет класс Server и реализует Интерфейс CustomTransportStrategy.

import { CustomTransportStrategy, Server } from "@nestjs/microservices";
export default class MyCustomStrategy extends Server implements CustomTransportStrategy {
    constructor(){
        super();
        // custom constructor logic here
    }
    // MUST implement this (defined by the CustomTransportStrategy interface)
    public async listen(done) {
        // custom code to start listening for messages
        // something like "SQS.listen(..)" etc
    }
    // MUST implement this (defined by the CustomTransportStrategy interface
    public async close() {
        // clean up code
        // something like "SQS.close(..)" etc
    }
}

Начальная загрузка вашей индивидуальной стратегии

Итак, вы видите, что приведенный выше код достаточно прост.
Но как вы используете его с микросервисом NestJS?

Нравится:

import { NestFactory } from '@nestjs/core';
import AppModule from './app/module';
import MyCustomStrategy from './my-custom-strategy';

async function bootstrap() {
    const customStrategy = new MyCustomStrategy();
    const app = await NestFactory.createMicroservice(
        AppModule,
        { strategy: customStrategy } // <-- OUR CUSTOM STRATEGY
    );
    app.listen(() => {
        console.log('Listening for HTTP Events ...');
    });
}
// Make sure to gracefully log any bootstrapping errors
bootstrap().catch(console.error);

Регистрация обработчиков событий

После того, как вы настроили свою собственную стратегию и загрузили ее в свой микросервис, вы можете начать регистрировать обработчики событий на своем контроллере так же, как и с любой другой стратегией транспортного уровня, используя встроенный декоратор MessagePattern (pattern):

import { Controller } from "@nestjs/common";
import { MessagePattern } from "@nestjs/microservices";
@Controller()
export default class AppController {
    @MessagePattern('foo')  // <-- handle the 'foo' event
    fooEventHandler(data) {
        console.log('Yay! We got data from foo!', data);
    }
}

Пользовательские стратегические события

Мы почти закончили!
Последнее, что нужно сделать, это убедиться, что всякий раз, когда мы получаем сообщения на нашем настраиваемом транспортном уровне, мы передаем их зарегистрированным обработчикам.

Это происходит внутри нашего класса стратегии, который мы определили ранее. Поскольку класс расширяет встроенный класс Server от @nestjs/microservices - он имеет доступ к зарегистрированным обработчикам.

В приведенном ниже фрагменте показана обновленная версия функции listen (…) из нашего класса MyCustomStrategy выше. Эта обновленная версия будет передавать входящие сообщения правильному обработчику:

export default class MyCustomStrategy extends Server implements CustomTransportStrategy {
    ...
    public async listen(done) {
        sqsConsumer.create({
            queueUrl: '...',
            handleMessage: async msg => {
                // Returns a Map of all the handlers
                const handlers = this.getHandlers();
                // Try to get a handler for this message
                const handler = handlers.get(msg.name);
                if (handler) {
                    try {
                        handler(msg);
                    }
                    catch (e) {
                        console.log(`Error while trying to handle the ${msg.name} event`, e);
                    }
                }
                else {
                    console.log(`No handler registered for the ${msg.name} event`);
                }
            }
        });
    }
}

Вот и все!

Это было не так уж плохо, правда?

Будем надеяться, что будущие выпуски NestJS будут включать встроенную поддержку дополнительных стратегий, но до тех пор - теперь у вас есть знания, чтобы создать их самостоятельно.

#nestjs #javascript # custom-transport-layer #microservices