Booster 프레임에서 구름 시뮬레이션💻🌩️

Booster의 가장 멋있는 점은 대부분의 기능이 하나의 추상적인 인터페이스 위에 위치하고 이 추상적인 인터페이스는 구름에서 온 것을 필요로 한다는 것이다.이 프레임워크 자체는 AWS, Azure 또는 Kubernetes에서 어떤 서비스도 호출하지 않았습니다.이것은 공급자가 맡은 일이다.
응용 프로그램을 개발할 때, 모든 데이터베이스, 클라우드 서비스, 또는 어떤 것의 세부 사항을 고려하고 싶지 않을 수도 있다.아마도 너는 나와 마찬가지로 수중의 기술/서비스의 모든 라이브러리나 SDK를 배우는 것을 싫어할 것이다.
이런 추상적인 덕분에, 당신은 증압기 개념(명령, 이벤트 등)을 사용하여 인코딩을 하고, 나머지 부분을 소홀히 하기만 하면 됩니다.그런데 밑에 무슨 일이 일어날까요?어디 보자👀

클라우드 및 로컬 개발


구름은 멋진 것이지만, 현지에서 개발하고 당신의 변화를 바로 보는 것보다 더 좋은 것은 무엇입니까?
그렇습니다. 어떤 것들은 특정 서비스의 작업 방식을 모의할 수 있습니다. 예를 들어 DynamoDB, 또는 누군가가 그들의 전체 Kubernetes 응용 프로그램을 실행할 수 있습니다. 예를 들어 MongoDB, MySQL, Redis 등입니다. 심지어 서버 프레임워크가 없으면 비교적 신속하게 응용 프로그램을 배치할 수 있지만 그 대가는 방대하고 난잡한 YAML 파일을 유지하는 것입니다.
일은 더욱 간단해야 한다. 너는 튼튼한 컴퓨터로 너의 응용 프로그램을 개발할 필요가 없다.
많은 이유들이 있지만, 그 외에, 내가 방금 묘사한 이유들, 사람들은 가장 간단한 방식으로 응용 프로그램을 작성하기로 결심했다. 아마도 express 서버나 비슷한 방식일 것이다.
만약 우리가 express 서버를 가지고 있다면, 우리가 구름 속의 응용 프로그램으로서는?이것은 현지 공급업체의 생각이다.

증압기 공급자가 현지에서 일하는 것을 실현하다



증압기 공급자를 실현하려면 두 개의 npm 패키지를 만들어야 합니다.
  • framework-provider-<name of your environment> - 이 패키지는 다음을 담당합니다.
  • 은 클라우드에서 데이터를 저장/검색하는 기능을 제공합니다.
  • 은 클라우드의 특정 대상을 증강 대상으로 변환합니다. 예를 들어 AWS 이벤트를 증강 대상으로 변환합니다.
  • framework-provider-<name of your environment>-infrastructure - 이 패키지는 다음을 담당합니다.
  • deploy 함수를 제공합니다. 이 함수는 클라우드 공급자에 필요한 모든 자원을 설정하고 코드를 정확하게 업로드합니다. 그리고 nuke 함수를 제공합니다. 이 함수는 배치된 모든 내용을 삭제하거나
  • 은 특정 환경에서 프로젝트를 실행하기 위해 서버와 모든 적당한 프로세스를 시작하는 start 함수를 제공합니다.이것은 내가 현지 공급업체에 사용할 것이다.
  • 로컬 제공 프로그램을 구현하고 있다는 점을 고려하여 다음과 같은 이름만 지정했습니다.
  • framework-provider-local
  • framework-provider-local-infrastructure
  • 로컬 공급자를 실현하기 위해 저는 express을 Booster가 제공하는 단점으로 사용하고 nedb을 사용할 것입니다. 이것은 NoSQL 데이터베이스의 로컬 파일 시스템 구현입니다. API는 MongoDB와 매우 유사합니다.NoSQL 데이터베이스가 아닌 경우 SQLite에 해당합니다.
    첫 번째 가방을 실현하기 시작합시다.

    공급자 인터페이스


    Booster의 공급자 인터페이스는 일반적인 TypeScript 인터페이스로 다음과 같은 방법으로 구현되어야 합니다.
    export const Provider = {
      events: {
        rawToEnvelopes: ...,
        forEntitySince: ...,
        latestEntitySnapshot: ...,
        store: ...,
      },
      readModels: {
        rawToEnvelopes: ...,
        fetch: ...,
        search: ...,
        store: ...,
        // ...
      },
      graphQL: {
        rawToEnvelope: ...,
        handleResult: ...,
      },
      api: {
        requestSucceeded,
        requestFailed,
      },
      // ...
    }
    
    기초를 실현하기 위해 rawToEnvelopes부터 이 함수들은 클라우드 데이터 형식에서 증강형 데이터 형식으로 전환됩니다.
    로컬 공급자의 경우 express을 사용하여 처리하기 때문에 데이터는 원래대로 도착합니다.
    export function rawEventsToEnvelopes(rawEvents: Array<unknown>): Array<EventEnvelope> {
      return rawEvents as Array<EventEnvelope>
    }
    
    export function rawReadModelEventsToEnvelopes(rawEvents: Array<unknown>): Array<ReadModelEnvelope> {
      return rawEvents as Array<ReadModelEnvelope>
    }
    
    rawToEnvelope 필드의 graphQL 함수에 대해 요청 ID, 연결 ID 또는 이벤트 유형과 같은 더 많은 정보를 요청으로부터 얻어야 합니다. 이러한 정보는 요청에 나타나기 때문에 작업을 간소화하기 위해 무시됩니다.
    export async function rawGraphQLRequestToEnvelope(
      request: express.Request
    ): Promise<GraphQLRequestEnvelope | GraphQLRequestEnvelopeError> {
      return {
        requestID: UUID.generate(),  // UUID.generate() provided by Booster
        eventType: 'MESSAGE',
        connectionID: undefined,
        value: request.body,
      }
    }
    
    이러한 기능이 실현됨에 따라 우리는 이미 단점을 Booster에 연결했다. 지금은 데이터를 저장하고 검색하는 방법을 가르쳐야 한다.

    로컬 데이터베이스 만들기


    NedB를 사용하여 Booster 응용 프로그램 데이터를 저장하는 경우 먼저 초기화해야 합니다.Provider과 동일한 파일에서 이 작업을 수행할 수 있습니다.
    import * as DataStore from 'nedb'
    import { ReadModelEnvelope, EventEnvelope } from '@boostercloud/framework-types'
    
    const events: DataStore<EventEnvelope> = new DataStore('events.json')
    const readModels: DataStore<ReadModelEnvelope> = new DataStore('read_models.json')
    
    NeDB는 테이블마다 하나의 파일을 사용하기 때문에 DataStore 두 개를 만들어 상호작용을 합니다.
    현재, 우리는 공급자가 필요로 하는 방법을 실현해야 한다. 예를 들어 store:
    async function storeEvent(event: EventEnvelope): Promise<void> {
      return new Promise((resolve, reject) => {
        events.insert(event, (err) => {
          err ? reject(err) : resolve()
        })
      })
    }
    
    async function storeReadModel(readModel: ReadModelEnvelope): Promise<void> {
      return new Promise((resolve, reject) => {
        readModels.insert(readModel, (err) => {
          err ? reject(err) : resolve()
        })
      })
    }
    
    유감스럽게도 NedB는 Promise 기반 API를 제공하지 않고 promisify을 제대로 사용할 수 없기 때문에 수동으로 포장해야 합니다.실현은 매우 간단하다.
    나머지 방법은 다음과 같은 적절한 질의를 수행하는 것입니다.
    async function readEntityLatestSnapshot(
      entityID: UUID, 
      entityTypeName: string
    ): Promise<EventEnvelope> {
      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<APIResult> {
      return {
        status: 'success',
        result: body,
      }
    }
    
    async function requestFailed(error: Error): Promise<APIResult> {
      const statusCode = httpStatusCodeFor(error)
      return {
        status: 'failure',
        code: statusCode,
        title: toClassTitle(error),
        reason: error.message,
      }
    }
    
    Provider의 모든 방법을 실현한 후에 우리는 기본적으로 첫 번째 가방을 완성했고 우리는 인프라 시설 열차에 뛰어들 수 있다🚂

    Express 서버로 모든 컨텐츠 연결

    Provider과 같은 상황에서 귀하의 Infrastructure 대상은 하나의 인터페이스에 부합되어야 합니다. 우리의 예시에서 이 인터페이스는 모든 내용을 초기화하는 start 방법입니다.여기에서 express 서버를 만들고 프레임워크 핵심에서 제공하는 함수를 호출하여 Booster에 연결합니다.
    먼저 express 서버를 초기화합니다.
    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의 다음 폴더에서 항상 전체 코드를 볼 수 있습니다.
  • packages/framework-provider-local
  • packages/framework-provider-local-infrastructure
  • 이 모든 것을 읽어 주셔서 감사합니다!즐거운 하루 되세요.
    흔적을 새기다

    좋은 웹페이지 즐겨찾기