hackathon/ARCHITECTURE_ALIGNMENT_REPORT.md
Christoph Wagner a489c15cf5 feat: Add complete HSP implementation with integration tests passing
Initial implementation of HTTP Sender Plugin following TDD methodology
  with hexagonal architecture. All 313 tests passing (0 failures).

  This commit adds:
  - Complete domain model and port interfaces
  - All adapter implementations (HTTP, gRPC, file logging, config)
  - Application services (data collection, transmission, backpressure)
  - Comprehensive test suite with 18 integration tests

  Test fixes applied during implementation:
  - Fix base64 encoding validation in DataCollectionServiceIntegrationTest
  - Fix exception type handling in IConfigurationPortTest
  - Fix CompletionException unwrapping in IHttpPollingPortTest
  - Fix sequential batching in DataTransmissionServiceIntegrationTest
  - Add test adapter failure simulation for reconnection tests
  - Use adapter counters for gRPC verification

  Files added:
  - pom.xml with all dependencies (JUnit 5, Mockito, WireMock, gRPC, Jackson)
  - src/main/java: Domain model, ports, adapters, application services
  - src/test/java: Unit tests, integration tests, test utilities
2025-11-20 22:38:55 +01:00

8.0 KiB

Architecture Alignment Report - Configuration

Date: 2025-11-20 Issue: Adapter code doesn't match actual Configuration domain model API Root Cause: Parallel AI agents generated code with mismatched APIs


Correct Architecture (From Domain Model)

Configuration Class Structure

System-Wide Settings (Configuration.java):

public final class Configuration {
    private final List<EndpointConfig> endpoints;     // Per-endpoint configs
    private final Duration pollingInterval;            // System-wide
    private final int bufferCapacity;                  // System-wide (300)
    private final String grpcHost;                     // gRPC target
    private final int grpcPort;                        // gRPC port
    private final boolean tlsEnabled;                  // TLS flag
    private final Duration reconnectDelay;             // gRPC reconnect (5s)
    private final int healthCheckPort;                 // Health endpoint (8080)
}

Per-Endpoint Settings (EndpointConfig.java):

public final class EndpointConfig {
    private final String url;                          // Endpoint URL
    private final Duration timeout;                    // Per-endpoint timeout!
    private final Map<String, String> headers;         // Per-endpoint headers!
}

Builder API (Correct Usage)

// ✅ CORRECT: Use static factory method
Configuration config = Configuration.builder()
    .endpoints(endpointList)              // List<EndpointConfig>
    .pollingInterval(Duration.ofSeconds(5))
    .bufferCapacity(300)
    .grpcHost("localhost")
    .grpcPort(50051)
    .tlsEnabled(false)
    .reconnectDelay(Duration.ofSeconds(5))
    .healthCheckPort(8080)
    .build();

// ❌ WRONG: Direct constructor access (private!)
Configuration.Builder builder = new Configuration.Builder(); // Won't compile!

What Adapters Are Doing Wrong

ConfigurationFileAdapter Issues

Wrong API Calls:

// ❌ WRONG
new Configuration.Builder()                     // Constructor is private!
builder.grpcServerAddress(String)               // Method doesn't exist
builder.grpcServerPort(int)                     // Method doesn't exist
builder.httpEndpoints(List<String>)             // Wrong type - needs List<EndpointConfig>
builder.pollingIntervalSeconds(int)             // Wrong type - needs Duration
builder.bufferSize(int)                         // Wrong name - should be bufferCapacity
builder.httpTimeoutSeconds(int)                 // Doesn't exist - timeout is per-endpoint!
builder.maxRetries(int)                         // Doesn't exist - adapter implementation detail
builder.retryIntervalSeconds(int)               // Doesn't exist - adapter implementation detail

config.getBufferSize()                          // Wrong name - should be getBufferCapacity()
config.getGrpcServerPort()                      // Wrong name - should be getGrpcPort()
config.getHttpEndpoints()                       // Wrong name - should be getEndpoints()

Correct API Calls:

// ✅ CORRECT
Configuration.builder()                         // Static factory method
    .grpcHost(String)                           // Correct method name
    .grpcPort(int)                              // Correct method name
    .endpoints(List<EndpointConfig>)            // Correct type
    .pollingInterval(Duration)                  // Correct type
    .bufferCapacity(int)                        // Correct name
    // No timeout here - it's per-endpoint in EndpointConfig!
    // No retry config - it's adapter implementation detail!
    .build()

config.getBufferCapacity()                      // Correct name
config.getGrpcPort()                            // Correct name
config.getEndpoints()                           // Correct name

HttpPollingAdapter Issues

Wrong Assumptions:

// ❌ WRONG: These methods don't exist in Configuration
config.getHttpTimeoutSeconds()      // Timeout is per-endpoint!
config.getMaxRetries()              // Retry is adapter detail!
config.getRetryIntervalSeconds()    // Retry is adapter detail!

Correct Approach:

// ✅ CORRECT: Get timeout from EndpointConfig
for (EndpointConfig endpoint : config.getEndpoints()) {
    Duration timeout = endpoint.getTimeout();    // Per-endpoint timeout
    Map<String,String> headers = endpoint.getHeaders();  // Per-endpoint headers

    // Retry logic is hardcoded in adapter (Req-FR-17)
    int maxRetries = 3;                          // Hardcoded per requirements
    int retryIntervalSeconds = 5;                // Hardcoded per requirements
}

📋 Requirements Traceability

Req-FR-17: HTTP Retry Logic

  • Requirement: "If the HTTP GET request fails HSP shall retry up to 3 times with 5-second intervals"
  • Configuration: http.max_retries = 3, http.retry_interval_seconds = 5
  • Correct Implementation: Hardcoded in HttpPollingAdapter (adapter implementation detail)
  • NOT in domain model Configuration class

Req-FR-12: HTTP Timeout

  • Requirement: "Configurable timeout per endpoint"
  • Correct Location: EndpointConfig.timeout (Duration)
  • NOT in Configuration class (it's per-endpoint, not system-wide!)

Req-FR-13: HTTP Headers

  • Requirement: "Custom headers per endpoint"
  • Correct Location: EndpointConfig.headers (Map<String,String>)
  • NOT in Configuration class (it's per-endpoint!)

🔧 Required Fixes

1. ConfigurationFileAdapter (16 errors)

Fix Strategy:

  1. Change new Configuration.Builder()Configuration.builder()
  2. Parse JSON to create List<EndpointConfig> from endpoint strings
  3. Use correct method names:
    • grpcHost() instead of grpcServerAddress()
    • grpcPort() instead of grpcServerPort()
    • endpoints() instead of httpEndpoints()
    • pollingInterval(Duration) instead of pollingIntervalSeconds(int)
    • bufferCapacity() instead of bufferSize()
  4. Remove non-existent methods:
    • httpTimeoutSeconds() - use EndpointConfig
    • maxRetries() - hardcode in adapter
    • retryIntervalSeconds() - hardcode in adapter
  5. Use correct getter names:
    • getBufferCapacity() instead of getBufferSize()
    • getGrpcPort() instead of getGrpcServerPort()
    • getEndpoints() instead of getHttpEndpoints()

2. HttpPollingAdapter (10 errors)

Fix Strategy:

  1. Remove calls to non-existent Configuration methods
  2. Hardcode retry logic (Req-FR-17):
    private static final int MAX_RETRIES = 3;
    private static final int RETRY_INTERVAL_SECONDS = 5;
    
  3. Get timeout and headers from EndpointConfig:
    Duration timeout = endpointConfig.getTimeout();
    Map<String,String> headers = endpointConfig.getHeaders();
    
  4. Implement pollEndpoint(String url, Map<String,String> headers, Duration timeout)

3. RateLimitedHttpPollingAdapter (3 errors)

Fix Strategy:

  1. Implement pollEndpoint(String url, Map<String,String> headers, Duration timeout)
  2. Same as HttpPollingAdapter

📝 Summary

The Problem:

  • Adapters were generated assuming Configuration contains per-endpoint settings (timeout, headers, retries)
  • Actual architecture: Configuration contains system-wide settings, EndpointConfig contains per-endpoint settings
  • Retry logic should be hardcoded in adapter (Req-FR-17), not in configuration

The Solution:

  1. ConfigurationFileAdapter: Use correct Configuration API with Builder pattern
  2. HttpPollingAdapter: Hardcode retry logic, get timeout/headers from EndpointConfig
  3. Follow hexagonal architecture: domain model is simple, adapters handle complexity

Architecture Principle:

  • Domain Model (Configuration, EndpointConfig): Simple, immutable value objects
  • Adapters (HttpPollingAdapter): Handle implementation details (retry logic, connection management)
  • Separation of Concerns: System-wide config vs per-endpoint config

Next Step: Apply these fixes to achieve compilation.