Skip to content

Commit

Permalink
feat: add circuit breaker support
Browse files Browse the repository at this point in the history
  • Loading branch information
jbl428 committed May 14, 2023
1 parent c327db8 commit 74c581f
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 2 deletions.
13 changes: 13 additions & 0 deletions lib/builders/circuit-breaker.builder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import CircuitBreaker from 'opossum';

export class CircuitBreakerBuilder {
constructor(private readonly options?: CircuitBreaker.Options) {}

async build(executor: () => Promise<Response>): Promise<Response> {
if (this.options == null) {
return await executor();
}

return await new CircuitBreaker(executor, this.options).fire();
}
}
1 change: 1 addition & 0 deletions lib/decorators/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export const REQUEST_BODY_METADATA = Symbol('REQUEST_BODY_METADATA');
export const REQUEST_FORM_METADATA = Symbol('REQUEST_FORM_METADATA');
export const REQUEST_HEADER_METADATA = Symbol('REQUEST_HEADER_METADATA');
export const RESPONSE_BODY_METADATA = Symbol('RESPONSE_BODY_METADATA');
export const CIRCUIT_BREAKER_METADATA = Symbol('CIRCUIT_BREAKER_METADATA');
17 changes: 15 additions & 2 deletions lib/supports/node-fetch.injector.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Injectable, type OnModuleInit } from '@nestjs/common';
import { DiscoveryService, MetadataScanner } from '@nestjs/core';
import { type InstanceWrapper } from '@nestjs/core/injector/instance-wrapper';
import { CircuitBreakerBuilder } from '../builders/circuit-breaker.builder';
import { type HttpRequestBuilder } from '../builders/http-request.builder';
import { type ResponseBodyBuilder } from '../builders/response-body.builder';
import {
CIRCUIT_BREAKER_METADATA,
HTTP_EXCHANGE_METADATA,
HTTP_INTERFACE_METADATA,
RESPONSE_BODY_METADATA,
Expand Down Expand Up @@ -43,14 +45,25 @@ export class NodeFetchInjector implements OnModuleInit {
return;
}

const circuitBreaker: CircuitBreakerBuilder =
Reflect.getMetadata(CIRCUIT_BREAKER_METADATA, prototype, methodName) ??
new CircuitBreakerBuilder(
this.httpInterfaceConfig?.circuitBreakerOption,
);
const responseBodyBuilder: ResponseBodyBuilder<unknown> | undefined =
Reflect.getMetadata(RESPONSE_BODY_METADATA, prototype, methodName);

httpRequestBuilder.setBaseUrl(baseUrl);

wrapper.instance[methodName] = async (...args: never[]) =>
await this.httpClient
.request(httpRequestBuilder.build(args), httpRequestBuilder.options)
await circuitBreaker
.build(
async () =>
await this.httpClient.request(
httpRequestBuilder.build(args),
httpRequestBuilder.options,
),
)
.then(async (response) => {
if (responseBodyBuilder != null) {
const res = await response.json();
Expand Down
2 changes: 2 additions & 0 deletions lib/types/http-interface-config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { type ClassTransformOptions } from 'class-transformer';
import type CircuitBreaker from 'opossum';
import { type HttpClient } from './http-client.interface';

export interface HttpInterfaceConfig {
timeout?: number;
httpClient?: HttpClient;
transformOption?: ClassTransformOptions;
circuitBreakerOption?: CircuitBreaker.Options;
}

0 comments on commit 74c581f

Please sign in to comment.