### Install @fastify/circuit-breaker Source: https://github.com/fastify/fastify-circuit-breaker/blob/main/README.md Use npm to install the circuit breaker plugin. ```bash npm i @fastify/circuit-breaker ``` -------------------------------- ### Basic Usage of @fastify/circuit-breaker Source: https://github.com/fastify/fastify-circuit-breaker/blob/main/README.md Register the plugin and apply the circuit breaker to a specific route using `preHandler`. This example demonstrates setting up a route that can optionally return an error or introduce a delay. ```javascript const fastify = require('fastify')() fastify.register(require('@fastify/circuit-breaker')) fastify.register(function (instance, opts, next) { instance.route({ method: 'GET', url: '/', schema: { querystring: { error: { type: 'boolean' }, delay: { type: 'number' } } }, preHandler: instance.circuitBreaker(), handler: function (req, reply) { setTimeout(() => { reply.send( req.query.error ? new Error('kaboom') : { hello: 'world' } ) }, req.query.delay || 0) } }) next() }) fastify.listen({ port: 3000 }, err => { if (err) throw err console.log('Server listening at http://localhost:3000') }) ``` -------------------------------- ### Circuit Breaker Error State Behavior Example Source: https://context7.com/fastify/fastify-circuit-breaker/llms.txt Demonstrates how the circuit opens after the number of 5xx responses reaches the `threshold`. Subsequent requests immediately receive a 503 without hitting the handler. After `resetTimeout` ms, the circuit moves to HALF-OPEN. ```javascript const fastify = require('fastify')() await fastify.register(require('@fastify/circuit-breaker'), { threshold: 3, timeout: 1000, resetTimeout: 1000 }) fastify.after(() => { fastify.get('/', { preHandler: fastify.circuitBreaker(), handler: (req, reply) => { reply.send(req.query.error ? new Error('kaboom') : { hello: 'world' }) } }) }) // Request 1: error=true → 500 Internal Server Error (failures: 1) // Request 2: error=true → 500 Internal Server Error (failures: 2) // Request 3: error=true → 503 Service Unavailable, circuit OPENS (failures: 3 = threshold) // { error: 'Service Unavailable', message: 'Circuit open', // statusCode: 503, code: 'FST_ERR_CIRCUIT_BREAKER_OPEN' } // After resetTimeout ms, circuit moves to HALF-OPEN // Next successful request → circuit closes and resets failure count // Next failing request in HALF-OPEN → circuit opens again immediately ``` -------------------------------- ### TypeScript Usage with Circuit Breaker Source: https://context7.com/fastify/fastify-circuit-breaker/llms.txt Demonstrates how to use the circuit breaker plugin with TypeScript, including type definitions for options and methods. It shows how to register the plugin and apply the circuit breaker to specific routes. ```typescript import fastify from 'fastify' import circuitBreaker from '@fastify/circuit-breaker' import type { FastifyCircuitBreakerOptions } from '@fastify/circuit-breaker' const app = fastify() const pluginOptions: FastifyCircuitBreakerOptions = { threshold: 3, timeout: 5000, resetTimeout: 5000, onCircuitOpen: async (req, reply) => { reply.statusCode = 503 return JSON.stringify({ message: 'circuit open' }) }, onTimeout: async (req, reply) => { reply.statusCode = 504 throw new Error('timed out') } } await app.register(circuitBreaker, pluginOptions) app.after(() => { app.get('/protected', { preHandler: app.circuitBreaker({ threshold: 2 }), handler: async (_req, reply) => { return { status: 'ok' } } }) }) await app.listen({ port: 3000 }) ``` -------------------------------- ### Plugin Registration Source: https://context7.com/fastify/fastify-circuit-breaker/llms.txt Register the plugin globally with optional default options that apply to all routes using `fastify.circuitBreaker()`. These options can be overridden for specific routes. ```APIDOC ## Plugin Registration Register the plugin globally with optional default options that apply to all routes using `fastify.circuitBreaker()`. ```js const fastify = require('fastify')() const circuitBreaker = require('@fastify/circuit-breaker') fastify.register(circuitBreaker, { threshold: 5, // max failures before opening circuit (default: 5) timeout: 10000, // ms before a slow response counts as a failure (default: 10000) resetTimeout: 10000, // ms in OPEN state before moving to HALF-OPEN (default: 10000) timeoutErrorMessage: 'Timeout', // default error message for timeouts circuitOpenErrorMessage: 'Circuit open', // default error message when circuit is open cache: 500 // max number of route states to cache (default: 500) }) fastify.listen({ port: 3000 }, err => { if (err) throw err console.log('Server listening at http://localhost:3000') }) ``` ``` -------------------------------- ### Configure @fastify/circuit-breaker Globally Source: https://github.com/fastify/fastify-circuit-breaker/blob/main/README.md Register the plugin with options to set global circuit breaker parameters like threshold, timeout, and reset timeout. Custom handlers for circuit open and timeout events can also be provided. ```javascript fastify.register(require('@fastify/circuit-breaker'), { threshold: 3, // default 5 timeout: 5000, // default 10000 resetTimeout: 5000, // default 10000 onCircuitOpen: async (req, reply) => { reply.statusCode = 500 throw new Error('a custom error') }, onTimeout: async (req, reply) => { reply.statusCode = 504 return 'timed out' } }) ``` -------------------------------- ### Register @fastify/circuit-breaker Plugin Globally Source: https://context7.com/fastify/fastify-circuit-breaker/llms.txt Register the plugin globally with optional default options that apply to all routes using `fastify.circuitBreaker()`. Configure failure threshold, timeout, reset timeout, and error messages. ```javascript const fastify = require('fastify')() const circuitBreaker = require('@fastify/circuit-breaker') fastify.register(circuitBreaker, { threshold: 5, // max failures before opening circuit (default: 5) timeout: 10000, // ms before a slow response counts as a failure (default: 10000) resetTimeout: 10000, // ms in OPEN state before moving to HALF-OPEN (default: 10000) timeoutErrorMessage: 'Timeout', // default error message for timeouts circuitOpenErrorMessage: 'Circuit open', // default error message when circuit is open cache: 500 // max number of route states to cache (default: 500) }) fastify.listen({ port: 3000 }, err => { if (err) throw err console.log('Server listening at http://localhost:3000') }) ``` -------------------------------- ### Configure @fastify/circuit-breaker Per Route Source: https://github.com/fastify/fastify-circuit-breaker/blob/main/README.md Customize circuit breaker options for a specific route by passing configuration directly to the `circuitBreaker()` utility. These settings will override any global configurations. ```javascript fastify.circuitBreaker({ threshold: 3, // default 5 timeout: 5000, // default 10000 resetTimeout: 5000 // default 10000 }) ``` -------------------------------- ### Error State Behavior — Threshold-Based Opening Source: https://context7.com/fastify/fastify-circuit-breaker/llms.txt The circuit opens after the number of 5xx responses reaches the `threshold`. Subsequent requests immediately receive a 503 without hitting the handler. After `resetTimeout` ms, the circuit moves to HALF-OPEN. The next successful request closes the circuit and resets the failure count. The next failing request in HALF-OPEN opens the circuit again immediately. ```APIDOC ## Error State Behavior — Threshold-Based Opening The circuit opens after the number of 5xx responses reaches the `threshold`. Subsequent requests immediately receive a 503 without hitting the handler. ```js const fastify = require('fastify')() await fastify.register(require('@fastify/circuit-breaker'), { threshold: 3, timeout: 1000, resetTimeout: 1000 }) fastify.after(() => { fastify.get('/', { preHandler: fastify.circuitBreaker(), handler: (req, reply) => { reply.send(req.query.error ? new Error('kaboom') : { hello: 'world' }) } }) }) // Request 1: error=true → 500 Internal Server Error (failures: 1) // Request 2: error=true → 500 Internal Server Error (failures: 2) // Request 3: error=true → 503 Service Unavailable, circuit OPENS (failures: 3 = threshold) // { error: 'Service Unavailable', message: 'Circuit open', // statusCode: 503, code: 'FST_ERR_CIRCUIT_BREAKER_OPEN' } // After resetTimeout ms, circuit moves to HALF-OPEN // Next successful request → circuit closes and resets failure count // Next failing request in HALF-OPEN → circuit opens again immediately ``` ``` -------------------------------- ### Registering and Using Circuit Breaker for Independent Routes Source: https://context7.com/fastify/fastify-circuit-breaker/llms.txt Register the circuit breaker plugin and apply it to individual routes. Each route has its own circuit, so '/unstable' failing does not affect '/stable'. ```javascript fastify.register(require('@fastify/circuit-breaker'), { threshold: 1 }) fastify.after(() => { // This route's circuit opens after 1 failure fastify.get('/unstable', { preHandler: fastify.circuitBreaker(), handler: (_req, reply) => reply.send(new Error('kaboom')) }) // This route has its own independent circuit — unaffected by /unstable fastify.get('/stable', { preHandler: fastify.circuitBreaker(), handler: (_req, reply) => reply.send({ hello: 'world' }) }) }) // GET /unstable → 503 Circuit open // GET /stable → 200 { hello: 'world' } ← still works ``` -------------------------------- ### Protect a Single Route with `fastify.circuitBreaker()` Source: https://context7.com/fastify/fastify-circuit-breaker/llms.txt Use `fastify.circuitBreaker()` to return a `preHandler` function that guards a single route with its own independent circuit. Options passed here override global plugin options for that specific route. Each call creates an independent circuit. ```javascript fastify.register(circuitBreaker, { threshold: 5, timeout: 10000, resetTimeout: 10000 }) fastify.after(() => { // Each call to fastify.circuitBreaker() creates an independent circuit fastify.get('/api/data', { preHandler: fastify.circuitBreaker({ threshold: 3, // override: open after 3 failures (not the global 5) timeout: 5000, // override: 5s response time limit resetTimeout: 5000 // override: try recovery after 5s }), handler: async (req, reply) => { // Simulate a call to an external service const data = await fetchExternalService() return data } }) // A second route gets its own completely isolated circuit fastify.get('/api/other', { preHandler: fastify.circuitBreaker(), // uses global defaults handler: async (req, reply) => { return { status: 'ok' } } }) }) // When threshold is reached, requests to /api/data return: // HTTP 503 { error: 'Service Unavailable', message: 'Circuit open', // statusCode: 503, code: 'FST_ERR_CIRCUIT_BREAKER_OPEN' } ``` -------------------------------- ### fastify.circuitBreaker([options]) — Protect a Route Source: https://context7.com/fastify/fastify-circuit-breaker/llms.txt Returns a `preHandler` function that guards a single route with its own independent circuit. Pass it to a route's `preHandler` option. Options passed here override global plugin options for that specific route. ```APIDOC ## `fastify.circuitBreaker([options])` — Protect a Route Returns a `preHandler` function that guards a single route with its own independent circuit. Pass it to a route's `preHandler` option. Options passed here override global plugin options for that specific route. ```js fastify.register(circuitBreaker, { threshold: 5, timeout: 10000, resetTimeout: 10000 }) fastify.after(() => { // Each call to fastify.circuitBreaker() creates an independent circuit fastify.get('/api/data', { preHandler: fastify.circuitBreaker({ threshold: 3, // override: open after 3 failures (not the global 5) timeout: 5000, // override: 5s response time limit resetTimeout: 5000 // override: try recovery after 5s }), handler: async (req, reply) => { // Simulate a call to an external service const data = await fetchExternalService() return data } }) // A second route gets its own completely isolated circuit fastify.get('/api/other', { preHandler: fastify.circuitBreaker(), // uses global defaults handler: async (req, reply) => { return { status: 'ok' } } }) }) // When threshold is reached, requests to /api/data return: // HTTP 503 { error: 'Service Unavailable', message: 'Circuit open', // statusCode: 503, code: 'FST_ERR_CIRCUIT_BREAKER_OPEN' } ``` ``` -------------------------------- ### Custom Open Circuit Handler Source: https://context7.com/fastify/fastify-circuit-breaker/llms.txt Implement a custom asynchronous handler invoked when the circuit opens. This allows for customized responses, such as returning a specific status code and JSON payload. ```javascript fastify.register(require('@fastify/circuit-breaker'), { threshold: 2, onCircuitOpen: async (req, reply) => { // req and reply are the standard Fastify objects reply.statusCode = 503 // Option A: return a custom JSON payload return JSON.stringify({ message: 'Service temporarily unavailable', retryAfter: 10 }) // Option B: throw to delegate to Fastify's error handler // throw new Error('circuit open') } }) fastify.after(() => { fastify.get('/', { preHandler: fastify.circuitBreaker(), handler: (_req, reply) => reply.send(new Error('kaboom')) }) }) // After 2 failures, circuit opens and subsequent requests receive: // HTTP 503 { "message": "Service temporarily unavailable", "retryAfter": 10 } ``` -------------------------------- ### Timeout-Based Circuit Breaker Opening Source: https://context7.com/fastify/fastify-circuit-breaker/llms.txt Configure the circuit breaker to open if response times exceed a specified timeout. Only 5xx errors count towards the failure threshold. ```javascript const fastify = require('fastify')() fastify.register(require('@fastify/circuit-breaker'), { threshold: 3, timeout: 50, // 50ms response time limit resetTimeout: 1000 }) fastify.after(() => { fastify.get('/', { preHandler: fastify.circuitBreaker(), handler: (req, reply) => { // Simulate slow external call setTimeout(() => reply.send({ hello: 'world' }), req.query.delay || 0) } }) }) // GET /?delay=100 → response took 100ms > 50ms timeout // → HTTP 503 { error: 'Service Unavailable', message: 'Timeout', // statusCode: 503, code: 'FST_ERR_CIRCUIT_BREAKER_TIMEOUT' } // After 3 timeout failures the circuit opens: // → HTTP 503 { error: 'Service Unavailable', message: 'Circuit open', // statusCode: 503, code: 'FST_ERR_CIRCUIT_BREAKER_OPEN' } ``` -------------------------------- ### Custom Timeout Handler Source: https://context7.com/fastify/fastify-circuit-breaker/llms.txt Define a custom asynchronous handler for when a route's response time exceeds the configured timeout. This handler can return custom payloads or throw errors. ```javascript fastify.register(require('@fastify/circuit-breaker'), { timeout: 50, onTimeout: async (req, reply) => { reply.statusCode = 504 // Return a plain string payload return 'timed out' // Or return structured JSON: // return JSON.stringify({ error: 'Gateway Timeout', retryAfter: 5 }) // Or throw to use Fastify error handling: // throw new Error('timed out') } }) fastify.after(() => { fastify.get('/', { preHandler: fastify.circuitBreaker(), handler: (_req, reply) => { setTimeout(() => reply.send({ hello: 'world' }), 100) // 100ms > 50ms timeout } }) }) // GET / → HTTP 504, body: "timed out" ``` -------------------------------- ### Customize Circuit Breaker Error Messages Source: https://github.com/fastify/fastify-circuit-breaker/blob/main/README.md Override the default error messages for circuit open and timeout errors by providing `timeoutErrorMessage` and `circuitOpenErrorMessage` options during plugin registration. ```javascript fastify.register(require('@fastify/circuit-breaker'), { timeoutErrorMessage: 'Ronf...', // default 'Timeout' circuitOpenErrorMessage: 'Oh gosh!' // default 'Circuit open' }) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.