npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

outbox-nestjs

v1.0.1

Published

An transactional outbox library for NestJs and Typeorm to solve dual write problem

Downloads

137

Readme

Transactional Outbox NestJs library

This library implements the transactional outbox pattern using Nestjs and Typeorm. For more information on transactional outbox patter, check here

Currently, the library supports event publishing to Kafka and RabbitMQ

Installation

npm install outbox-nestjs -s

Context

Outbox pattern guarantees data consistency for services that, as part of a business process, needs to persist an entity and also publish and event/message to a broker.

To achieve this, the message is stored in the database as part of the transaction that updates the business entities. A separate process then sends the messages to the message broker. This library implements this using the polling publisher pattern

The message that is persisted in the database is called the Outbox entity which looks like below

Outbox Entity

@Entity()
export class Outbox {

   @PrimaryGeneratedColumn(`uuid`)
   id: string;

   @Column()
   aggregateId: string

   @Column()
   messagePayload: string

   @Column()
   eventType: string

   @CreateDateColumn()
   createdAt: Date
}

| Outbox Entity Properties | Meaning | |--------------------------|-----------------------------------------------------------------------------------------------| | id | UUID primary key for the outbox entity | | aggregateId | This represents the Id of the aggregate. i:e entity that is being saved along with the outbox | | messagePayload | Message payload to be published. Should be in JSON string format | | eventType | This represents the type of event. i:e OrderProcessedEvent | | createdAt | When the event was created. Event are published in reverse chronological order. i:e FIFO |

Configuration

App Module configuration

In your NestJs application, navigate the app.module.ts and make the following configuration. The configuration can either one of the two below

  • Kafka Publisher configuration
  • RabbitMQ configuration

However, regardless of the event queue, there are two common configuration properties as can be seen below

| OutboxModule Properties | Meaning | |-------------------------|--------------------------------------------------------------------------------------------------| | queueType | The type of message queue to publish the message. This can either KAFKA or RABBITMQ | | datasource | This is the datasource configured for your application for connecting to the underlying database |

Kafka Publisher Configuration

If you will be publishing to Kafka, your configuration should look something like this below. We are going to add the OutboxModule in the imports section of the @Module decorator

import {MessageQueueType, OutboxModule} from "outbox-nestjs";

imports: [
  OutboxModule.forRoot({
    kafkaOptions: {
      clientId: `test-application`,
      brokers: [`localhost:9092`],
      topic: `outbox-topic`
    },
    queueType: MessageQueueType.KAFKA,
    datasource: connectionSource
  }),
]

| Kafka Options Properties | Meaning | |--------------------------|---------------------------------------------------------------------------| | clientId | This is the name of your service or whatever you want to call your client | | brokers | This the broker url(s). Supports an array for multiple brokers | | topic | The topic name to send your messages to |

RabbitMQ Configuration

If you are using RabbitMQ, your configuration should look something like this below. We are going to add the OutboxModule in the imports section of the @Module decorator

import {MessageQueueType, OutboxModule} from "outbox-nestjs";

imports: [
  OutboxModule.forRoot({
    rabbitOptions: {
      exchange: `sample-exchange`,
      connectionString: `amqp://guest:guest@localhost:5672`
    },
    queueType: MessageQueueType.RABBIT_MQ,
    datasource: connectionSource
  }),
]

| Kafka Options Properties | Meaning | |--------------------------|----------------------------------------------------------| | exchange | This is the rabbitMQ exchange to message publishing | | connectionString | This is the connection string for connecting to rabbitMQ |

Datasource Configuration

This library requires a datasource in order to fetch data from the outbox table. Typically, your datasource configuration would look something like below

import { Outbox } from "outbox-nestjs";


const config: TypeOrmModuleOptions = {
   type: "xxxx",
   host: `xxx`,
   port: xxxx,
   username: `xxxx`,
   password: `xxxx`,
   database: `xxxx`,
   entities: [`xxx`, Outbox],
   migrationsRun: true,
   migrations: ["dist/domain/migrations/*{.ts,.js}"],
   autoLoadEntities: true,
   synchronize: true,
   logger: "advanced-console"
};

The important part of the above configuration is that we have to add the Outbox entity to the entities array

Polling publisher

The library uses nestjs ScheduleModule to poll and publish to the message broker. You need to initiate the module. In app.module.ts, add the following

@Module({
   imports: [
      ScheduleModule.forRoot()
   ],
})

Database Migrations

The Typeorm configuration from above has synchronize:true, which would create the Outbox table in the database, however, DO NOT USE THIS IN PRODUCTION!!!

You should create the Outbox table in your database, choosing the right data type for each property

Other Considerations

There are some details to be aware of when using this library

  • The default polling interval is 1 Second for now
  • This library would try to publish the events at least once. However, there can be cases where an event is published more than once.
    Your clients should be Idempotent
  • While the implementation tries to publish the events in order which they arrive, the order may not be guaranteed ;)

Author

Nriagu Chidubem