-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d05c294
commit 2fc8c36
Showing
60 changed files
with
449 additions
and
144 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
# Broker | ||
|
||
The `Broker` is the interface to the underlying message broker. It is responsible for the transmission of messages between the producer and the consumer. | ||
|
||
## Internal Broker Architecture | ||
|
||
Internally, the broker is defined by the `Broker`, `Producer`, and `Consumer` adapters and their broker-specific implementations. | ||
|
||
## :package: `@ts-messaging/common` | ||
|
||
### `Broker` | ||
|
||
The broker interface is defined by the `createProducer` and `createConsumer` methods. The `createProducer` method is used to create a `Producer` instance and the `createConsumer` method is used to create a `Consumer` instance and automatically register them with the broker. | ||
|
||
```ts | ||
export interface Broker extends Connectable{ | ||
createProducer(config: unknown): Producer; | ||
createConsumer(config: unknown): Consumer; | ||
|
||
findChannel(name: string): Promise<Channel | null>; | ||
} | ||
``` | ||
|
||
### `Producer` | ||
|
||
The sole responsibility of the `Producer` is to transmit messages to the broker. The `Producer` is created by the `Broker` and is automatically registered with the remote broker. | ||
|
||
```ts | ||
export interface Producer extends Connectable { | ||
produce(message: any): Promise<unknown>; | ||
} | ||
``` | ||
|
||
### `Consumer` | ||
|
||
On this highest level, the only responsibility of the `Consumer` is to subscribe to channels. The `Consumer` is created by the `Broker` and is automatically registered with the remote broker. | ||
|
||
```ts | ||
export interface Consumer extends Connectable { | ||
subscribe(channels: Channel[]): Promise<void>; | ||
} | ||
``` | ||
|
||
## :package: `@ts-messaging/client` | ||
|
||
### `AbstractBroker` | ||
|
||
The `Broker` interface is extended by a caching mechanism. The `AbstractBroker` is responsible for caching the `Channel` instances. | ||
|
||
```ts | ||
export abstract class AbstractBroker<TChannel extends Channel> implements Broker { | ||
|
||
protected readonly channels = new Cache<string, TChannel>((key: string) => | ||
this.loadChannel(key) | ||
); | ||
|
||
protected abstract loadChannel(topicName: string): Promise<TChannel | null>; | ||
|
||
async findChannel(name: string): Promise<TChannel | null> { | ||
return this.channelCache.find(name); | ||
} | ||
|
||
abstract createConsumer(config: unknown): Consumer; | ||
abstract createProducer(config: unknown): Producer; | ||
abstract connect(): Promise<void>; | ||
abstract disconnect(): Promise<void>; | ||
} | ||
``` | ||
|
||
### `AbstractConsumer` | ||
|
||
The `AbstractConsumer` is responsible for the transmission of messages to the `Controller` instances. They are registered within the `AbstractConsumer` and are called when a message is received. The implementation is highly broker-specific. | ||
|
||
```ts | ||
export abstract class AbstractConsumer implements Consumer { | ||
protected readonly controllers: Controller[] = []; | ||
|
||
registerController(controller: Controller): void { | ||
this.controllers.push(controller); | ||
} | ||
|
||
abstract subscribe(channels: Channel[]): Promise<void>; | ||
abstract connect(): Promise<void>; | ||
abstract disconnect(): Promise<void> | ||
} | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,63 @@ | ||
# Channel | ||
|
||
The `Channel` is a resource of the `Broker`. It is a message transmission path. Each channel holds its associated contract and can use them to encode and decode the entire messages. | ||
The `Channel` is a resource of the `Broker`. It is a message transmission path. Each channel can determine its associated contract. | ||
|
||
## Internal Topic Architecture | ||
## Internal Channel Architecture | ||
|
||
Internally, the channel is defined by `Channel`, `AbstractChannel`, and their registry-specific implementations. | ||
|
||
## :package: `@ts-messaging/common` | ||
|
||
### `Channel` | ||
```ts | ||
export interface Channel { | ||
readonly name: string; | ||
readonly name: string; | ||
|
||
findContract(): Promise<Contract | null>; | ||
} | ||
``` | ||
|
||
### `ChannelFactory` | ||
The `ChannelFactory` is used by the `Broker` to create a `Channel` from the name of the channel. The `ChannelFactory` is broker-specific and is implemented by each client package. | ||
|
||
```ts | ||
export interface ChannelFactory{ | ||
produce(input: { name: string }): Promise<Channel>; | ||
} | ||
``` | ||
|
||
## :package: `@ts-messaging/client` | ||
|
||
### `AbstractChannel` | ||
|
||
The `AbstractChannel` is the base class for all broker-specific implementations of the `Channel` interface. The `AbstractChannel` is responsible for caching the contract associated with the channel. | ||
|
||
```ts | ||
import { Schema } from "./Schema"; | ||
|
||
export abstract class AbstractContract implements Channel { | ||
|
||
abstract readonly name: string; | ||
protected contract: Promise<Contract | null> | undefined; | ||
|
||
//The broker-specific loading of the contract | ||
protected abstract loadContract(): Promise<Contract | null>; | ||
|
||
//Caching mechanism for the contract | ||
async findContract(): Promise<Contract | null> { | ||
if (this.contract) { | ||
return this.contract; | ||
} | ||
|
||
this.contract = this.loadContract(); | ||
const value = await this.contract; | ||
|
||
if (!value) { | ||
this.contract = undefined; | ||
} | ||
|
||
return value; | ||
} | ||
} | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Controller | ||
|
||
The `Controller` is highly broker-specific. It is serves as a mediator and controller between endpoints and consumers. | ||
|
||
## Internal Controller Architecture | ||
|
||
Internally the controller is represented by `Controller`, `XXX`, `XXX`, and their broker-specific implementations. | ||
|
||
## :package: `@ts-messaging/common` | ||
|
||
### `Controller` | ||
|
||
Internally, the controller is defined by the `Controller` interface. It contains a reference to its consumer and a `handleMessage` method that is invoked by the consumer when a message is received. | ||
|
||
```ts | ||
export interface Controller { | ||
readonly consumer: Consumer; | ||
handleMessage(message: Message): Promise<{ | ||
invocations: number; | ||
}>; | ||
} | ||
``` | ||
|
||
### `ControllerFactory` | ||
The `ControllerFactory` is used by the `Client` to create a `Controller` from an annotated class. The `ControllerFactory` is broker-specific and is implemented by each client package. | ||
|
||
```ts | ||
export interface ControllerFactory { | ||
produce(controllerConstructor: Constructor): Promise<Controller>; | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,20 @@ | ||
# Endpoint | ||
|
||
The `Endpoint` is a novel concept that is used to deliver a message to the business logic of the application. The endpoint therefore determines if a message can be committed by the consumer after it has been processed. | ||
The `Endpoint` is a novel concept that is used to deliver a message to the business logic of the application. The endpoint therefore determines if a message can be committed by the consumer after it has been processed. As its implementation is highly broker-dependent, the `endpoint is only implemented in the client package. | ||
|
||
## Internal Contract Architecture | ||
## Internal Endpoint Architecture | ||
|
||
Internally, the endpoint is defined by the `Endpoint` interface and their broker-specific implementations. | ||
|
||
## :package: `@ts-messaging/common` | ||
|
||
### `Endpoint` | ||
|
||
```ts | ||
export interface MessageEndpoint<M extends Message = Message> { | ||
channelName: string; | ||
schema: Record<string, number[]> | number[]; | ||
endpoint: (message: M) => Promise<void>; | ||
export interface MessageEndpoint { | ||
name: string; | ||
channel: Channel; | ||
payloadContractVersion: ContractVersion | null; | ||
endpoint: (...args: any[]) => Promise<void>; | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Message | ||
|
||
The `Message` describes the common representation of a message inside the framework. It is used by the `Broker` to transmit messages between the producer and the consumer. | ||
|
||
## Internal Message Architecture | ||
|
||
Internally, the message is defined by the `Message` and `MessageData` interface and their broker-specific implementations. | ||
|
||
## :package: `@ts-messaging/common` | ||
|
||
### `Message` | ||
|
||
The message interface contains the `channel`, `payload`, `contractVersion`, and `meta` properties. The `payload` is a schema object and `contractVersion` the associated version of the contract used to encode the message, and the `meta` is the broker-specific metadata. | ||
|
||
```ts | ||
export interface Message<T extends SchemaObject = any> { | ||
readonly channel: Channel; | ||
payload: T | null; | ||
contractVersion: ContractVersion<T> | null; | ||
meta: MessageMetadata; | ||
} | ||
``` | ||
|
||
### `MessageMetadata` | ||
|
||
The `MessageMetadata` interface is a placeholder for broker-specific metadata. | ||
|
||
```ts | ||
export interface MessageMetadata {} | ||
``` |
Oops, something went wrong.