Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
248 changes: 170 additions & 78 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,51 @@
- Safely routing and transferring data and control across service and application boundaries
- Coordinating transactional work that requires a high-degree of reliability

#### Installation
## Installation

To start building Azure Service Bus-based microservices, first install the required packages:

```bash
$ npm i --save @azure/service-bus @niur/nestjs-service-bus
$ npm i nestjs-azure-service-bus-transporter
```
#### Overview

## Server

To use the Azure Service Bus strategy, pass the following options object to the `createMicroservice()` method:

```typescript
// main.ts

const app = await NestFactory.createMicroservice<MicroserviceOptions>(AppModule, {
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
AppModule,
{
strategy: new AzureServiceBusServer({
connectionString:
"Endpoint=sb://<Name>.servicebus.windows.net/;SharedAccessKeyName=<SharedAccessKeyName>;SharedAccessKey=<SharedAccessKey>",
options: {},
}),
}
);
```

To use in a hybrid application, pass the following options object to the `connectMicroservice()` method:

```typescript
// main.ts
const app = await NestFactory.create(AppModule);

await app.connectMicroservice({
strategy: new AzureServiceBusServer({
connectionString: 'Endpoint=sb://<Name>.servicebus.windows.net/;SharedAccessKeyName=<SharedAccessKeyName>;SharedAccessKey=<SharedAccessKey>',
options: {}
connectionString:
"Endpoint=sb://<Name>.servicebus.windows.net/;SharedAccessKeyName=<SharedAccessKeyName>;SharedAccessKey=<SharedAccessKey>",
options: {},
}),
});

await app.startAllMicroservices();
await app.listen(3000);
```

#### Options

The <strong>Azure Service Bus</strong> strategy exposes the properties described below.
Expand All @@ -61,9 +84,117 @@ The <strong>Azure Service Bus</strong> strategy exposes the properties described
</tr>
</table>

#### Client
### Queue Consumer

To access the original Azure Service Bus message use the `Queue` decorator as follows:

```typescript
import { Queue } from '@niur/nestjs-service-bus';
import { ServiceBusReceiver } from '@azure/service-bus';
import { Payload, Ctx } from '@nestjs/microservices';
@Queue({
queueName: 'sample-topic',
receiveMode: 'peekLock', // or receiveAndDelete
options:{
autoCompleteMessages:true,
}
})
getMessages(
@Payload() message: ServiceBusMessage,@Ctx() context:AzureServiceBusContext) {
const serviceBusReceiver:ServiceBusReceiver= context.getArgs()[0];
console.log(message);
}
```

Options

<table>
<tr>
<td><code>queueName</code></td>
<td>Name of the queue we want to receive from.</td>
</tr>
<tr>
<td><code>receiveMode</code></td>
<td>Represents the receive mode for the receiver. (read more <a href="https://docs.microsoft.com/azure/service-bus-messaging/message-transfers-locks-settlement#peeklock" rel="nofollow" target="_blank">here</a>).</td>
</tr>
<tr>
<td><code>subQueueType</code></td>
<td>Represents the sub queue that is applicable for any queue or subscription. (read more <a href="https://docs.microsoft.com/azure/service-bus-messaging/service-bus-dead-letter-queues" rel="nofollow" target="_blank">here</a>).</td>
</tr>
<tr>
<td><code>maxAutoLockRenewalDurationInMs</code></td>
<td>The maximum duration in milliseconds until which the lock on the message will be renewed by the sdk automatically.</td>
</tr>
<tr>
<td><code>skipParsingBodyAsJson</code></td>
<td>Option to disable the client from running JSON.parse() on the message body when receiving the message.</td>
</tr>
<tr>
<td><code>options</code></td>
<td>Options used when subscribing to a Service Bus queue or subscription.</td>
</tr>
</table>

### Topic Consumer

To access the original Azure Service Bus message use the `Subscription` decorator as follows:

```typescript
import { Topic } from '@niur/nestjs-service-bus';
import { Payload, Ctx } from '@nestjs/microservices';
import { ServiceBusReceiver } from '@azure/service-bus';
@Subscription({
topic: 'sample-topic',
subscription: 'sample-subscription',
receiveMode: 'peekLock', // or receiveAndDelete
options:{
autoCompleteMessages:true,
}
})
getMessages(@Payload() message: ServiceBusMessage) {
const serviceBusReceiver: ServiceBusReceiver = context.getArgs()[0];
console.log(message);
}
```

Options

<table>
<tr>
<td><code>topic</code></td>
<td>Name of the topic for the subscription we want to receive from.</td>
</tr>
<tr>
<td><code>subscription</code></td>
<td>Name of the subscription (under the `topic`) that we want to receive from.</td>
</tr>
<tr>
<td><code>receiveMode</code></td>
<td>Represents the receive mode for the receiver. (read more <a href="https://docs.microsoft.com/azure/service-bus-messaging/message-transfers-locks-settlement#peeklock" rel="nofollow" target="_blank">here</a>).</td>
</tr>
<tr>
<td><code>subQueueType</code></td>
<td>Represents the sub queue that is applicable for any queue or subscription. (read more <a href="https://docs.microsoft.com/azure/service-bus-messaging/service-bus-dead-letter-queues" rel="nofollow" target="_blank">here</a>).</td>
</tr>
<tr>
<td><code>maxAutoLockRenewalDurationInMs</code></td>
<td>The maximum duration in milliseconds until which the lock on the message will be renewed by the sdk automatically.</td>
</tr>
<tr>
<td><code>skipParsingBodyAsJson</code></td>
<td>Option to disable the client from running JSON.parse() on the message body when receiving the message.</td>
</tr>
<tr>
<td><code>options</code></td>
<td>Options used when subscribing to a Service Bus queue or subscription.</td>
</tr>
</table>

## Client

```typescript
// app.module.ts

@Module({
imports: [
AzureServiceBusModule.forRoot([
Expand Down Expand Up @@ -97,105 +228,66 @@ The <strong>Azure Service Bus</strong> strategy exposes the properties described

```

```typescript
Since AzureServiceBusModule is a global module you can inject Clients into other modules providers and even controllers.

```typescript
//example.service.ts
//provider
@Injectable()
constructor(
@Inject('SB_CLIENT') private readonly sbClient: AzureServiceBusClientProxy,
) {}
export class exampleService {
constructor(
@Inject("SB_CLIENT") private readonly sbClient: AzureServiceBusClientProxy
) {}
}
```

```typescript
//example.controller.ts
//controller
@Controller("example")
export class exampleController {
constructor(
@Inject("SB_CLIENT") private readonly sbClient: AzureServiceBusClientProxy
) {}
}
```

##### Producer
### Producer

Event-based

```typescript

const pattern = {
name: 'sample-topic', // topic name
options: {}
}; // queue name
name: "sample-topic", // topic/queue name
options: {},
};
const data = {
body: 'Example message'
body: "Example message",
};

this.sbClient.send(pattern, data).subscribe((response) => {
console.log(response); // reply message
});

```

Message-based

```typescript

const pattern = {
name: 'sample-topic', // topic name
options: {}
}; // queue name
name: "sample-topic", // topic/queue name
options: {},
};
const data = {
body: 'Example message'
body: "Example message",
};
this.sbClient.emit(pattern, data);
```


##### Consumer

To access the original Azure Service Bus message use the `Subscription` decorator as follows:


```typescript

@Subscription({
topic: 'sample-topic',
subscription: 'sample-subscription',
receiveMode: 'peekLock', // or receiveAndDelete
})
getMessages(@Payload() message: ServiceBusMessage) {
console.log(message);
}
```

Options

<table>
<tr>
<td><code>topic</code></td>
<td>Name of the topic for the subscription we want to receive from.</td>
</tr>
<tr>
<td><code>subscription</code></td>
<td>Name of the subscription (under the `topic`) that we want to receive from.</td>
</tr>
<tr>
<td><code>receiveMode</code></td>
<td>Represents the receive mode for the receiver. (read more <a href="https://docs.microsoft.com/azure/service-bus-messaging/message-transfers-locks-settlement#peeklock" rel="nofollow" target="_blank">here</a>).</td>
</tr>
<tr>
<td><code>subQueueType</code></td>
<td>Represents the sub queue that is applicable for any queue or subscription. (read more <a href="https://docs.microsoft.com/azure/service-bus-messaging/service-bus-dead-letter-queues" rel="nofollow" target="_blank">here</a>).</td>
</tr>
<tr>
<td><code>maxAutoLockRenewalDurationInMs</code></td>
<td>The maximum duration in milliseconds until which the lock on the message will be renewed by the sdk automatically.</td>
</tr>
<tr>
<td><code>skipParsingBodyAsJson</code></td>
<td>Option to disable the client from running JSON.parse() on the message body when receiving the message.</td>
</tr>
<tr>
<td><code>options</code></td>
<td>Options used when subscribing to a Service Bus queue or subscription.</td>
</tr>
</table>



## Stay in touch

* Author - [Niurmiguel](https://github.com/Niurmiguel)
- Author - [Santiagomrn](https://github.com/Santiagomrn)
- Author - [Niurmiguel](https://github.com/Niurmiguel)

## License
Nestjs Azure Service Bus is [MIT licensed](LICENSE).

Nestjs Azure Service Bus is [MIT licensed](LICENSE).
3 changes: 2 additions & 1 deletion lib/azure-service-bus.context.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ServiceBusReceiver } from "@azure/service-bus";
import { BaseRpcContext } from "@nestjs/microservices/ctx-host/base-rpc.context";

type AzureServiceBusContextArgs = [];
type AzureServiceBusContextArgs = [ServiceBusReceiver];

export class AzureServiceBusContext extends BaseRpcContext<AzureServiceBusContextArgs> {
constructor(args: AzureServiceBusContextArgs) {
Expand Down
13 changes: 12 additions & 1 deletion lib/decorators/subscriber.decorator.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { EventPattern } from "@nestjs/microservices";

import { SB_SUBSCRIBER_METADATA } from "../azure-service-bus.constants";
import { SbSubscriberMetadata } from "../metadata";
import {
MetaOrMetaFactory,
SbQueueMetadataOptions,
SbSubscriptionMetadataOptions,
} from "../interfaces";

Expand Down Expand Up @@ -44,3 +44,14 @@ export function Subscription(
}
};
}

export const Queue = (metadata: SbQueueMetadataOptions) => {
const data = { ...metadata, topic: metadata.queueName };
delete data.queueName;
return Subscription({
...data,
subscription: null,
});
};

export const Topic = Subscription;
9 changes: 9 additions & 0 deletions lib/interfaces/subscriber.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,12 @@ export interface SbSubscriptionMetadataOptions
export interface SbSubscriberTypeMap {
subscription: SbSubscriptionMetadataOptions;
}


export interface SbQueueMetadataOptions
extends Omit<SbSubscriberMetadataOptions,"subscription"> {
/**
* Name of the topic for the subscription we want to receive from.
*/
queueName: string;
}
Loading