WalzoneInterview Prep
📞 Interviewing soon? Practice with a realistic AI mock phone interview — it calls you, then scores you. First 15 min FREE →

Design Patterns · Expert · question 72 of 100

How can you apply the Chain of Responsibility pattern in a fault-tolerant system to ensure request processing even in case of partial system failures?

📕 Buy this interview preparation book: 100 Design Patterns questions & answers — PDF + EPUB for $5

The Chain of Responsibility pattern is often used in software systems to handle requests in a flexible and extensible way. In a fault-tolerant system, we can apply this pattern to ensure request processing even in case of partial system failures.

The idea behind this pattern is to create a chain of handlers that receive a request and try to handle it. If a handler is unable to process the request, it passes the request to the next handler in the chain. This continues until either a handler successfully processes the request or the request reaches the end of the chain without being handled.

To apply this pattern in a fault-tolerant system, we can use a variation of the pattern called the CircuitBreaker pattern. The CircuitBreaker pattern is designed to handle faults and partial failures in distributed systems by opening a circuit when a service fails, and closing it when the service recovers.

In a fault-tolerant system, we can use the CircuitBreaker pattern to create a chain of handlers where each handler is responsible for handling a specific type of request. If a handler is unable to handle a request due to a partial system failure, it can open the circuit and pass the request to the next handler in the chain. The CircuitBreaker pattern is responsible for monitoring the health of the system and opening or closing circuits as needed.

Here’s an example implementation of this pattern in Java:

public abstract class RequestHandler {
    private RequestHandler nextHandler;
    private CircuitBreaker circuitBreaker;

    public void setNextHandler(RequestHandler handler) {
        this.nextHandler = handler;
    }

    public void setCircuitBreaker(CircuitBreaker circuitBreaker) {
        this.circuitBreaker = circuitBreaker;
    }

    public void handleRequest(Request request) {
        if (!circuitBreaker.isOpen()) {
            if (canHandle(request)) {
                handle(request);
            } else {
                if (nextHandler != null) {
                    nextHandler.handleRequest(request);
                } else {
                    circuitBreaker.open();
                }
            }
        }
    }

    protected abstract boolean canHandle(Request request);

    protected abstract void handle(Request request);
}

public class CircuitBreaker {
    private boolean open = false;

    public boolean isOpen() {
        return open;
    }

    public void open() {
        open = true;
    }

    public void close() {
        open = false;
    }
}

public class FaultTolerantSystem {
    private final RequestHandler firstHandler;

    public FaultTolerantSystem() {
        CircuitBreaker circuitBreaker = new CircuitBreaker();
        RequestHandler handler1 = new Handler1();
        RequestHandler handler2 = new Handler2();

        handler1.setCircuitBreaker(circuitBreaker);
        handler1.setNextHandler(handler2);
        handler2.setCircuitBreaker(circuitBreaker);

        firstHandler = handler1;
    }

    public void handleRequest(Request request) {
        firstHandler.handleRequest(request);
    }
}

In this example, we have an abstract ‘RequestHandler‘ class that defines the basic functionality for handling requests. Each concrete handler subclass implements the ‘canHandle‘ and ‘handle‘ methods to determine if they can handle a request and to handle the request if they can.

The ‘CircuitBreaker‘ class monitors the health of the system and opens or closes the circuit as needed. The ‘FaultTolerantSystem‘ class initializes the handlers and sets up the chain of responsibility.

When a request is received by the ‘FaultTolerantSystem‘, it is passed to the first handler in the chain. If the circuit is open due to a partial system failure, the request is not processed by any handler and the circuit remains open. If the request is successfully handled by a handler, the circuit remains closed. If the first handler cannot handle the request, it is passed to the next handler in the chain. This process continues until the request is successfully handled or the end of the chain is reached and the circuit is opened.

Overall, applying the Chain of Responsibility pattern with the CircuitBreaker pattern can help ensure request processing in a fault-tolerant system even in case of partial system failures.

Reading is step one. Saying it out loud is the interview. Our AI interviewer calls your phone and runs a realistic Design Patterns interview — then scores it.
📞 Practice Design Patterns — free 15 min
📕 Buy this interview preparation book: 100 Design Patterns questions & answers — PDF + EPUB for $5

All 100 Design Patterns questions · All topics