Рубрики
Uncategorized

Эмуляция облака в рамках усилителя 💻🌩️

Облако прохладно, и все это джаз, но что лучше, чем развиваться на месте и видение ваших изменений мгновенно на экспресс-сервере?. Помечено webdev, узел, teadercript, devops.

Одним из прохладных вещей о усилении является то, что большая часть его функциональности сидит на вершине абстрактного интерфейса, который ожидает некоторых вещей из облака. Сама рамок не имеет ни одного звонка к любому сервису от AWS, Azure, или Kubernetes. Это работа провайдер пакеты.

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

Благодаря этой абстракции вы просто код, используя концепции усилителя (команду, события и т. Д.) и забывают о остальных. Но что происходит снизу? Давайте посмотрим 👀

Облако круто, и все это джаз, но что лучше, чем развиваться на местном уровне и мгновенно видеть ваши изменения?

Да, есть вещи, которые эмулируют работу специфических услуг, такие как Dynamodb, или есть люди, которые управляют всеми своими приложениями Kubernetes, со всеми необходимыми процессами, такими как Mongodb, MySQL, Redis и т. Д. Или даже такие вещи, как Serverless Framework, которые развертывают ваше приложение относительно быстро, но по стоимости поддержания огромного, грязного ямля.

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

Из-за многих причин, но вдоль них те, которые я только что описал, люди решили кодировать свое приложение в простейшим способом возможным, возможно, Экспресс Сервер или одинаково.

Что если у нас было Экспресс Сервер, который вел себя как наше приложение в облаке? Это идея с местным провайдером.

Для реализации поставщика усилителя вам нужно будет создать два NPM Пакеты:

  • Рамочная провайдера - <Имя вашей среды> — Этот пакет отвечает за:

    • Предоставьте функции для хранения/извлечения данных из вашего облака.
    • Преобразуйте специфические объекты вашего облака в Booster, например Преобразование события AWS в бустер один.
  • Рамочная провайдера - <Название вашей среды> -Infrastructure — Этот пакет отвечает за:

    • Обеспечить Развертывание . Функция, которая установит все необходимые ресурсы в вашем облачном провайдере и загружать код правильно, а также Nuke Функция, которая удаляет все развернутое, ИЛИ
    • Обеспечить Начать Функция, которая начнет сервер и все соответствующие процессы для запуска проекта в определенной среде. Это тот, который я буду использовать для местного провайдера Отказ

Учитывая, что я реализую местного провайдера, я только что назвал их как:

  • Рамочная провайдера - местный
  • Рамочная провайдера - местная инфраструктура

Для реализации локального провайдера я буду использовать Экспресс Это будет действовать как конечные точки, предоставленные усилителем, и NEDB , который является локальной, файловой системой внедрение базы данных NoSQL, с API очень похожим на MongoDB. Это будет эквивалент SQLite, но для баз данных NoSQL.

Давайте начнем реализовать первый пакет.

Интерфейс Provider Booster — это обычный интерфейс TeampStry, который должен иметь его методы, реализуемые, реализация может выглядеть так:

export const Provider = {
  events: {
    rawToEnvelopes: ...,
    forEntitySince: ...,
    latestEntitySnapshot: ...,
    store: ...,
  },
  readModels: {
    rawToEnvelopes: ...,
    fetch: ...,
    search: ...,
    store: ...,
    // ...
  },
  graphQL: {
    rawToEnvelope: ...,
    handleResult: ...,
  },
  api: {
    requestSucceeded,
    requestFailed,
  },
  // ...
}

Чтобы начать реализацию оснований, давайте начнем с Rawtoenvelopes которые являются функциями, которые преобразуют из типа облачных данных в усилитель один.

В случае местного провайдера данные прибудут, как это, как мы отвечаем за ее обращение с Экспресс Итак, реализация довольно проста:

export function rawEventsToEnvelopes(rawEvents: Array): Array {
  return rawEvents as Array
}

export function rawReadModelEventsToEnvelopes(rawEvents: Array): Array {
  return rawEvents as Array
}

В случае Rawtoenvelope Функция для graphql Поле, нам придется получить дополнительную информацию из запроса, например, идентификатор запроса, идентификатор соединения или тип события, который придет в запросе, чтобы упростить вещи, давайте игнорируем их:

export async function rawGraphQLRequestToEnvelope(
  request: express.Request
): Promise {
  return {
    requestID: UUID.generate(),  // UUID.generate() provided by Booster
    eventType: 'MESSAGE',
    connectionID: undefined,
    value: request.body,
  }
}

С этими функциями реализованы, у нас уже есть наши конечные точки, связанные с усилителем, теперь мы просто должны научить его хранить/извлекать данные!

Учитывая, что мы будем использовать NEDB для хранения наших данных приложений Booster, нам нужно будет инициализировать его первым. Мы можем сделать это в одном файле, что и Провайдер выполнение:

import * as DataStore from 'nedb'
import { ReadModelEnvelope, EventEnvelope } from '@boostercloud/framework-types'

const events: DataStore = new DataStore('events.json')
const readModels: DataStore = new DataStore('read_models.json')

NEDB использует файл для каждой «таблицы», поэтому мы создаем два DataStore с, чтобы взаимодействовать с.

Теперь мы должны реализовать методы, которые требуют поставщиков, например, хранить :

async function storeEvent(event: EventEnvelope): Promise {
  return new Promise((resolve, reject) => {
    events.insert(event, (err) => {
      err ? reject(err) : resolve()
    })
  })
}

async function storeReadModel(readModel: ReadModelEnvelope): Promise {
  return new Promise((resolve, reject) => {
    readModels.insert(readModel, (err) => {
      err ? reject(err) : resolve()
    })
  })
}

К сожалению, NEDB не предоставляет Обещание на основе API, и не играет хорошо с похищать Итак, мы должны обернуть его вручную. Реализация довольно проста.

Остальные методы — это вопрос реализации надлежащих запросов, например:

async function readEntityLatestSnapshot(
  entityID: UUID, 
  entityTypeName: string
): Promise {
  const queryPromise = new Promise((resolve, reject) =>
    this.events
      .find({ entityID, entityTypeName, kind: 'snapshot' })
      .sort({ createdAt: -1 }) // Sort in descending order
      .exec((err, docs) => {
        if (err) reject(err)
        else resolve(docs)
      })
  )
}

Есть некоторые другие методы, которые могут быть немного запутаны, но они также действуют в качестве взаимодействия в какой-то момент, как управление ответами HTTP:

async function requestSucceeded(body?: any): Promise {
  return {
    status: 'success',
    result: body,
  }
}

async function requestFailed(error: Error): Promise {
  const statusCode = httpStatusCodeFor(error)
  return {
    status: 'failure',
    code: statusCode,
    title: toClassTitle(error),
    reason: error.message,
  }
}

После внедрения всех методов Провайдер Мы в значительной степени сделаны с первой упаковкой, и мы можем прыгать на инфраструктурный поезд 🚂

В том же случае, что и Провайдер Ваш Инфраструктура Объект должен соответствовать интерфейсу, который в нашем случае является Начать Метод, который инициализирует все. Здесь мы создадим Экспресс Сервер и проволоки его в усилитель, вызывая функции, которые предусматривает основное ядро.

Давайте начнем с помощью инициализации Экспресс Сервер:

export const Infrastructure = {
  start: (config: BoosterConfig, port: number): void => {
    const expressServer = express()
    const router = express.Router()
    const userProject: UserApp = require(path.join(process.cwd(), 'dist', 'index.js'))
    router.use('/graphql', graphQLRouter(userProject))
    expressServer.use(express.json())
    expressServer.use(router)
    expressServer.listen(port)
  },
}

Здесь мы импортируем приложение пользователя, чтобы получить доступ ко всем функциям общественного бустера (набрано в UserApp тип).

Вы можете увидеть, что единственная конечная точка в данный момент — /graphql. , И это то, что мы собираемся настроить сейчас:

function graphQLRouter(userApp: UserApp) {
  const router = express.Router()
  this.router.post('/', async (req, res) => {
    const response = await userApp.boosterServeGraphQL(req)  // entry point
    res.status(200).json(response.result)
  })
}

И вот и это, нам нужно позвонить только BoosterserveGraphql в приложении пользователя.

Поскольку мы уже предоставили все необходимые методы в пакете поставщика, Booster имеет доступ ко всем возможностям инфраструктуры, и он будет использовать все, что они должны быть, не нужно писать больше кода! 🚀

Я буду продолжать работать над улучшением местного провайдера, например, добавление приятных веществ, тестов, тесты и больше вкусностей 😉, но вы всегда можете проверить полный код в следующих папках Booster Repo:

  • Пакеты/Рамочная провайдера - Местный
  • Пакеты/Рамочная провайдера - местная инфраструктура

Спасибо, что читали все это! Иметь потрясающий день,

Ник

Оригинал: «https://dev.to/boostercloud/emulating-the-cloud-within-booster-framework-17o8»