logo
All experience

Mentorship Program

Independent2024
JavaSpring BootRabbitMQJUnit5Mockito
Overview

A structured mentorship engagement focused on backend engineering fundamentals. The work covered message queue architecture, extensible system design, batch processing patterns, and test-driven development. Every project was built from scratch with production quality as the target, not just passing requirements.

Key work
01Built a queue-backed messaging system supporting both real-time delivery and scheduled dispatch from a single producer interface.
02Designed an extensible provider abstraction using the abstract factory pattern and open-closed principle. Adding a new provider requires a new class, not a change to existing code.
03Implemented batch processing with per-item retry logic and a circuit breaker at the service boundary to handle downstream failures without blocking the queue.
04Wrote unit and integration tests with JUnit5 and Mockito. Reached 85% code coverage across all modules.

Messaging System

The system needed to support two delivery modes from a single interface: immediate dispatch and scheduled delivery. A naive implementation would have split the producer logic into two separate paths, duplicating message construction and routing responsibility.

I built it on RabbitMQ with a routing layer that selects the delivery path based on message configuration. Immediate messages are pushed to a direct exchange. Scheduled messages are held and dispatched by a cron worker at the configured time. Both paths share the same message format and producer interface — callers choose a delivery mode, not a delivery mechanism.

Extensible Provider Design

Integrating multiple external providers for the same operation — where the interface is identical but the underlying implementation differs — is a common pattern that becomes a maintenance problem when provider selection is handled with branches inside the sending logic.

I used the abstract factory pattern: a factory per provider, a common interface, and a registry that selects the right factory based on configuration. The send path never changes when a new provider is added. Adding support for a new provider means adding a new factory class. The existing code is not modified. This is the open-closed principle applied directly: open for extension, closed for modification.

Batch Processing and Resilience

Batch jobs that call external services need to handle partial failures without stopping the run, and they need to protect against hammering a degraded downstream with unbounded retries.

I implemented retry with exponential backoff at the per-item level so a single failing record does not block the rest of the batch. A circuit breaker sits at the service boundary: if the downstream failure rate crosses a threshold, the circuit opens and the batch fails fast rather than continuing to exhaust retries against a service that is already struggling. The batch can resume safely from where it left off once the downstream recovers.