Summary
Enable applications to override services defined by their dependencies. This unblocks the http_cache → http_client architecture (#784), where http_cache needs to override http_client's transport service to inject caching behavior.
Context
Current Problem:
Applications cannot override services from their dependencies. When app A depends on app B and tries to override B's services, validation fails with:
ValueError: Service with name <service> is not defined, but override flag is set.
Root Cause:
Validation happens too early during ServiceDefinitionCollection.__iter__ (harp/services/models.py:176-177), only checking services within a single YAML file rather than the full container context.
Current Workaround:
http_cache manually modifies http_client's service definition after loading (see harp_apps/http_cache/app.py:22-38).
Input
Service Definition YAML:
# http_cache/services.yml overriding http_client service
services:
- name: "http_client"
override: true # or override: "merge"
type: "httpx.AsyncClient"
defaults:
transport: !ref "http_cache.transport"
Output and Testing Scenarios
Expected Behavior:
- Happy Path: http_cache overrides http_client service → cache transport is injected successfully
- Chained Override: A → B → C where both A and B override same service → A's override takes precedence
- Sibling Conflict: A → C ← B where both try to override same service → clear error with dependency context
- Invalid Override: App tries to override non-existent service → helpful error message
Possible Implementation
Chosen Approach: Container-aware validation
Modify ServiceDefinitionCollection.__iter__ to accept an optional container parameter for validation context:
def __iter__(self, container=None):
# When validating override flag:
if service.override:
# Check both collection AND container
if service.name not in _map and (not container or service.name not in container):
raise ValueError(f"Service {service.name} not defined...")
Benefits:
- Minimal code change
- Backward compatible (container parameter is optional)
- Preserves existing validation flow
Override Semantics
Two modes will be supported:
-
override: true (replacement mode)
- Behavior to be determined after documenting current implementation
- Either complete replacement or type & args only
-
override: "merge" (merge mode)
- Merges arguments and defaults with base service
- Override values win in conflicts
- Can change type if explicitly specified
- Deep merge for nested dictionaries
Validation Rules
Override Direction: Unidirectional (dependent → dependency only)
- ✅ http_cache can override http_client services
- ❌ http_client cannot override http_cache services
Conflict Resolution:
- Chained overrides allowed (A → B → C)
- Sibling conflicts raise error with dependency graph context
Current Challenges
- Need to document existing override behavior before finalizing
override: true semantics
- Container reference must be passed through the loading chain
- Error messages need to include dependency graph context for clarity
Acceptance Criteria
Related
Summary
Enable applications to override services defined by their dependencies. This unblocks the http_cache → http_client architecture (#784), where http_cache needs to override http_client's transport service to inject caching behavior.
Context
Current Problem:
Applications cannot override services from their dependencies. When app A depends on app B and tries to override B's services, validation fails with:
Root Cause:
Validation happens too early during
ServiceDefinitionCollection.__iter__(harp/services/models.py:176-177), only checking services within a single YAML file rather than the full container context.Current Workaround:
http_cache manually modifies http_client's service definition after loading (see harp_apps/http_cache/app.py:22-38).
Input
Service Definition YAML:
Output and Testing Scenarios
Expected Behavior:
Possible Implementation
Chosen Approach: Container-aware validation
Modify
ServiceDefinitionCollection.__iter__to accept an optional container parameter for validation context:Benefits:
Override Semantics
Two modes will be supported:
override: true(replacement mode)override: "merge"(merge mode)Validation Rules
Override Direction: Unidirectional (dependent → dependency only)
Conflict Resolution:
Current Challenges
override: truesemanticsAcceptance Criteria
ServiceDefinitionCollectionoverride: trueandoverride: "merge"modes work as specifiedharp_apps/http_cache/tests/test_settings.pyRelated