0.0.6 • Published 5 months ago

monita-libs v0.0.6

Weekly downloads
-
License
MIT
Repository
github
Last release
5 months ago

Monita Microservices Libraries

This directory contains shared libraries used across the Monita microservices architecture. Below is a guide on how to use each library in your services.

Auth Library (@/libs/auth)

The auth library provides OTP (One-Time Password) functionality.

Usage

import { OtpModule, OtpService } from '@/libs/auth';

@Module({
  imports: [
    OtpModule
  ]
})

// In your service:
constructor(private readonly otpService: OtpService) {}

// Generate OTP
const result = await this.otpService.generateOtp(phone, purpose, options);

// Verify OTP
const isValid = await this.otpService.verifyOtp({
  phone,
  otp,
  reference,
  purpose
});

Cache Library (@/libs/cache)

Redis-based caching implementation for the microservices.

Usage

import { CacheModule, CacheService } from '@/libs/cache';

@Module({
  imports: [
    CacheModule.register()
  ]
})

// In your service:
constructor(private readonly cacheService: CacheService) {}

// Basic cache operations
await this.cacheService.set('key', 'value', ttlSeconds);
const value = await this.cacheService.get('key');
await this.cacheService.del('key');

// Hash operations
await this.cacheService.hset('key', 'field', 'value');
const hashValue = await this.cacheService.hget('key', 'field');
const allValues = await this.cacheService.hgetall('key');

NATS Library (@/libs/nats)

Message queue implementation using NATS for inter-service communication.

Environment Variables

Each service should have these NATS-related environment variables:

# Required
NATS_URL=nats://localhost:4222
NATS_SERVICE_QUEUE=service_queue  # Replace 'service' with your service name (e.g., payment_queue)

# Optional with defaults
NATS_TIMEOUT=5000
NATS_RECONNECT=true
NATS_RECONNECT_TIME_WAIT=2000
NATS_MAX_RECONNECT_ATTEMPTS=10

Basic Usage

import { NatsModule, NatsService, NatsMessageDto } from '@/libs/nats';

// Register in your module (Simple)
@Module({
  imports: [
    NatsModule.register({
      transport: Transport.NATS,
      options: {
        servers: ['nats://localhost:4222'],
        queue: 'my_service_queue',
      },
    }),
  ],
})

// Or register with async configuration
@Module({
  imports: [
    NatsModule.registerAsync({
      imports: [ConfigModule],
      useFactory: (configService: ConfigService) => ({
        transport: Transport.NATS,
        options: {
          servers: [configService.get('NATS_URL')],
          queue: configService.get('NATS_SERVICE_QUEUE'),
        },
      }),
      inject: [ConfigService],
    }),
  ],
})

// In your service:
constructor(private readonly natsService: NatsService) {}

// Send a message
const message: NatsMessageDto = {
  pattern: 'your.pattern',
  data: { your: 'data' },
};
await this.natsService.send(message);

// Emit an event
await this.natsService.emit(message);

Using Decorators

import { NatsEventPattern } from '@/libs/nats';

@Controller()
export class YourController {
  @NatsEventPattern('your.pattern')
  async handleEvent(data: any) {
    // Handle the event with automatic logging
  }
}

Advanced Features

  1. Automatic Logging: All NATS communications are automatically logged with timing information.

  2. Error Handling: Built-in error handling and retries.

  3. Timeouts: Configurable timeouts for all operations.

  4. Connection Management: Automatic connection management with reconnection support.

  5. Type Safety: Use NatsMessageDto for type-safe message handling.

// Example with type safety
interface PaymentData {
  amount: number;
  currency: string;
}

const message: NatsMessageDto = {
  pattern: 'payment.process',
  data: {
    amount: 100,
    currency: 'USD',
  } as PaymentData,
};

const result = await this.natsService.send<PaymentResponse>(message);

BullMQ Library (@/libs/bullmq)

Background job processing library for handling long-running tasks, retries, and scheduled jobs.

Usage

import { BullmqModule } from '@/libs/bullmq';
import { join } from 'path';

// Register in your module
@Module({
  imports: [
    BullmqModule.forFeature({
      queueName: 'my-queue',
      processorPath: join(__dirname, 'processors', 'my.processor.js'),
      concurrency: 3,
      defaultJobOptions: {
        attempts: 3,
        backoff: {
          type: 'exponential',
          delay: 1000,
        },
      },
    }),
  ],
})

// Create a job processor (my.processor.ts)
import { Job } from 'bullmq';

export default async function myProcessor(job: Job) {
  try {
    console.log(`Processing job ${job.id}`);
    await job.updateProgress(50);
    // Your job logic here
    return { processed: true };
  } catch (error) {
    console.error(`Error processing job ${job.id}:`, error);
    throw error;
  }
}

// In your service
@Injectable()
export class MyService {
  constructor(
    @Inject('BullQueue_my-queue')
    private myQueue: Queue,
  ) {}

  async addJob(data: any) {
    // Regular job
    await this.myQueue.add('job-name', data);

    // Delayed job
    await this.myQueue.add('delayed-job', data, {
      delay: 5000, // 5 seconds
    });

    // Repeatable job
    await this.myQueue.add('repeatable-job', data, {
      repeat: {
        every: 1000 * 60, // Every minute
      },
    });
  }
}

Features

  1. Queue Management: Create, pause, resume, and clean queues
  2. Job Processing: Handle long-running tasks with progress tracking
  3. Automatic Retries: Configure retry attempts and backoff strategies
  4. Job Scheduling: Delayed and repeatable jobs
  5. Event Handling: Monitor job completion and failures
  6. Resource Cleanup: Automatic cleanup on application shutdown

Environment Variables

# BullMQ Configuration
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=your_password

Common Library (@/libs/common)

Shared utilities, constants, interfaces, and enums used across services.

Usage

import {
  NOTIFICATION_QUEUE,
  generateRandomString,
  formatPhoneNumber,
  OtpPurpose,
  SwaggerConfig,
} from '@/libs/common';

// Use constants
console.log(NOTIFICATION_QUEUE); // 'notification'

// Use utility functions
const randomStr = generateRandomString();
const formattedPhone = formatPhoneNumber('+2341234567890');

// Use enums and interfaces
const purpose: OtpPurpose = OtpPurpose.REGISTRATION;

Best Practices

  1. Always import from the library's main entry point (e.g., @/libs/auth not @/libs/auth/src/*)
  2. Use TypeScript types and interfaces provided by the libraries
  3. Follow the async/await pattern when working with services
  4. Configure modules properly in your service's root module
  5. Handle errors appropriately as most library functions are promise-based

Configuration

Most libraries require configuration through environment variables. Ensure these are set in your service's .env file:

# Cache Configuration
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=your_password

# NATS Configuration
NATS_URL=nats://localhost:4222
NATS_SERVICE_QUEUE=service_queue  # Replace 'service' with your service name (e.g., payment_queue)

# Other configurations...