CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Build Commands
# Full build with tests
mvn clean install
# Build without tests (quick)
mvn clean install -DskipTests
# Run all tests
mvn test
# Run a single test class
mvn test -pl mayfly-core -Dtest=ModelInstanceTest
# Run a single test method
mvn test -pl mayfly-adapter -Dtest=DeepSeekModelAdapterTest#testCreateChatModel
# Run mutation tests (PIT)
mvn org.pitest:pitest-maven:mutationCoverage
# Build Docker image
docker build -t mayfly .
# Run with Docker Compose
docker compose up
Project Architecture
Mayfly is a multi-module Maven project (Java 17, Spring Boot 3.2, Spring AI 1.0-M6) providing enterprise-grade model routing for Spring AI.
Module Dependency Chain
mayfly-core (interfaces & domain models)
→ mayfly-router (routing strategies)
→ mayfly-loadbalancer (load balancing)
→ mayfly-failover (failover/retry)
→ mayfly-circuitbreaker (Resilience4j-based)
→ mayfly-monitor (Micrometer metrics)
→ mayfly-adapter (model implementations)
→ mayfly-spring-boot-starter (auto-configuration)
→ mayfly-demo (example application)
Core Interfaces (mayfly-core)
- ModelRouter: Unified entry point (
chat(),stream(),async()) - ModelRegistry: Manages available model instances, supports tag-based filtering
- ModelConfig/ModelInstance: Configuration vs runtime state separation (Config POJO + Instance with health/cooldown/activeRequests)
- HealthStatus: Enum with HEALTHY/UNHEALTHY/COOLDOWN states
Routing & Load Balancing
- RouterStrategy (mayfly-router): 3 implementations —
FixedRouterStrategy(always same model),WeightedRouterStrategy(weight-based),RuleBasedRouterStrategy(SpEL expression rules with priority ordering) - LoadBalancer (mayfly-loadbalancer):
RoundRobinLoadBalancerandWeightedRoundRobinLoadBalancer
Enterprise Features
- FailoverHandler (mayfly-failover): Marks failed models as COOLDOWN, selects backup candidates, supports retryable exception class matching
- CircuitBreakerManager (mayfly-circuitbreaker): Wraps Resilience4j CircuitBreaker + RateLimiter per model
- MetricsCollector (mayfly-monitor): Interface +
MicrometerMetricsCollector(real) +NoOpMetricsCollector(fallback); covers call success/failure, failover, streaming chunks/latency
Model Adapters (mayfly-adapter)
Each adapter follows a uniform pattern: a ModelAdapter factory + inner ChatModel implementation + inner HttpClient implementation. Currently supports:
- ZhiPu (GLM-4) — custom API,
@Componentregistered via component scan - Tongyi (Qwen) — custom API
- DeepSeek — OpenAI-compatible API
- OpenAI — standard API
- Claude — Anthropic API
- Wenxin — Baidu API
- Xinghuo — iFlytek API
BaseHttpClient provides shared RestTemplate (sync) and WebClient (streaming) implementations. BaseStreamingChatModel provides reusable SSE parsing for OpenAI-compatible models.
Auto-Configuration (mayfly-spring-boot-starter)
MayflyPropertiesbindsmayfly.*YAML configMayflyAutoConfigurationwires all beans, strategy-selection via@ConditionalOnPropertyDefaultModelRouterorchestrates: select → circuit-breaker → call → failover → retryDefaultModelRegistryreads config from properties, delegates ChatModel creation to ModelAdapter
Testing Patterns
- Interface contract tests (e.g.,
ModelAdapterInterfaceContractTest,HttpClientInterfaceContractTest) validate all implementations enforce the same contract - WireMock tests for HTTP layer (
BaseHttpClientWireMockTest) - PIT mutation testing with 80% mutation/coverage thresholds
- Streaming-specific tests for each streaming-capable adapter
- Exception/boundary tests for edge cases (nulls, empty lists, concurrent access)
- Integration test (
MayflyFullIntegrationTest) verifies the complete routing pipeline