Coder Social home page Coder Social logo

useful-patterns-ts's Introduction

daily-snippets

Table of Contents

  1. Specification pattern
  2. Circuit breaker

Specification pattern

A real-life example for open for extension closed for modification

export enum Race {
  HighElf,
  Redguard,
  Breton,
  Khajiit,
  Orc,
}

export enum Gear {
  Dagger,
  Bows,
  MuffledBoots,
  HeavyArmor,
  Shield,
  FortifyAlchemy,
  FortifySmithing,
}

export enum Skill {
  OneHanded,
  Archery,
  Sneak,
  Illusion,
  Conjuration,
  Alchemy,
  Enchanting,
  Smithing,
}

export enum Spell {
  Frenzy,
  Invisibility,
}

export enum Shout {
  AuraWhisper = 'Aura Whisper',
  BendWill = 'Bend Will',
  ElementalFury = 'Elemental Fury',
  SlowTime = 'Slow Time',
}

export class Character {
  constructor(
    public readonly name: string,
    public readonly race: Race,
    public readonly coreSkills: Skill[],
    public readonly gears: Gear[],
    public readonly spells?: Spell[],
    public readonly shouts?: Shout[],
  ) {}
}

export class RaceSpecification extends CompositeSpecification<Character> {
  constructor(private readonly race: Race) {
    super();
  }

  IsSatisfiedBy(candidate: Character): boolean {
    return candidate.race === this.race;
  }
}

export class IsCharacterGoodAtStealthSpecification extends CompositeSpecification<Character> {
  IsSatisfiedBy(candidate: Character): boolean {
    const stealthGears = [Gear.MuffledBoots];
    return stealthGears.some((gear) => candidate.gears.includes(gear));
  }
}

export class CharacterFilter {
  executeSpecification(
    characters: Character[],
    spec: ISpecification<Character>,
  ) {
    return characters.filter((character) => spec.IsSatisfiedBy(character));
  }
}

// Client code(usage):
const khajiitSpec = new RaceSpecification(Race.Khajiit);
const stealthSpec = new IsCharacterGoodAtStealthSpecification();
const combinatorSpec = khajiitSpec.and(stealthSpec);

export const stealthArcherKhajiit = new Character(
  'Stealth Archer Khajiit',
  Race.Khajiit,
  [Skill.Archery, Skill.Sneak, Skill.Illusion],
  [Gear.Bows, Gear.MuffledBoots],
);

const characters = [stealthArcherKhajiit];

const cf = new CharacterFilter();
const result = cf.executeSpecification(characters, combinatorSpec);

expect(result).toStrictEqual([stealthArcherKhajiit]);

Circuit Breaker

class CircuitBreaker {
  private isOpen: boolean;
  private failureCount: number;
  private readonly maxFailures: number;
  private readonly resetTimeout: number;
  private lastFailureTime: number;

  constructor(maxFailures: number, resetTimeout: number) {
    this.isOpen = false;
    this.failureCount = 0;
    this.maxFailures = maxFailures;
    this.resetTimeout = resetTimeout;
    this.lastFailureTime = 0;
  }

  public async executeAction<T>(action: () => Promise<T>): Promise<T> {
    if (this.isOpen && this.isResetTimeoutExpired()) {
      this.reset();
    }

    if (this.isOpen) {
      return Promise.reject(new Error("Circuit breaker is open"));
    }

    try {
      const result = await action();
      this.onActionSuccess();
      return result;
    } catch (error) {
      this.onActionFailure();
      return Promise.reject(error);
    }
  }

  private isResetTimeoutExpired(): boolean {
    return Date.now() - this.lastFailureTime >= this.resetTimeout;
  }
  
  private reset() {
    this.isOpen = false;
    this.failureCount = 0;
    console.log(`Circuit breaker is reset: ${new Date().toISOString()}`);
  }

  private onActionSuccess() {
    this.failureCount = 0;
  }

  private onActionFailure() {
    this.failureCount++;
    
    console.log(`failureCount: ${this.failureCount}`);

    if (this.failureCount >= this.maxFailures) {
      this.trip();
    }
  }

  private trip() {
    this.isOpen = true;
    this.lastFailureTime = Date.now();
    console.log(`Circuit breaker is open: ${new Date().toISOString()}`);
  }
}

// Example usage
// Maximum 3 failures within 5 seconds
const circuitBreaker = new CircuitBreaker(3, 5000);

const riskyAction = () => {
  return new Promise((resolve, reject) => {
    // Simulating some risky operation
    const randomNumber = Math.random();
    if (randomNumber < 0.6) {
      resolve("Success!");
    } else {
      reject(new Error("Something went wrong."));
    }
  });
};

// Perform action using the circuit breaker
setInterval(async () => {
  try {
   const result = await circuitBreaker.executeAction(riskyAction);
   console.log(result);
  } catch(error) {
    console.log(error?.message);
  }
}, 100);

useful-patterns-ts's People

Contributors

myalcinkayadev avatar

Stargazers

Utku avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.