You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The current py-libp2p implementation uses hardcoded TTL (Time To Live) values throughout the codebase, which is not a good practice for several reasons:
Lack of flexibility - Users cannot adjust TTL values for their specific use cases
Inconsistent values - Different components use different hardcoded TTLs
Maintenance issues - Changes require code modifications instead of configuration
Testing difficulties - Hard to test different TTL scenarios
Current State Analysis
Hardcoded TTL Values Found
Component
File
TTL Value
Purpose
Identify Push
libp2p/identity/identify_push/identify_push.py
7200 seconds (2 hours)
Peer address TTL
PubSub
libp2p/pubsub/utils.py
7200 seconds (2 hours)
Message TTL
DHT
libp2p/kad_dht/utils.py
24 * 60 * 60 seconds (24 hours)
Provider record TTL
DHT Provider
libp2p/kad_dht/utils.py
22 * 60 * 60 seconds (22 hours)
Provider record TTL
Issues with Current Approach
# Example from identify_push.pyawaitself._host.peerstore.add_addrs(
peer_id, addrs, 7200# Hardcoded 2 hours
)
Problems:
❌ No way to configure for different network conditions
❌ Cannot optimize for mobile vs desktop environments
❌ Difficult to test edge cases
❌ Inconsistent with Go libp2p best practices
Go libp2p Best Practices
Go libp2p implements a well-structured, configurable TTL system:
// Different TTLs based on contextfunc (ps*peerstore) AddAddr(peerID, addr ma.Multiaddr, ttl time.Duration) {
// TTL is passed as parameter, not hardcoded
}
Recommended Solution
1. Create TTL Configuration Module
# libp2p/config/ttl.pyfromdataclassesimportdataclassfromtypingimportOptional, Listimporttrio@dataclassclassTTLConfig:
"""Configurable TTL values for different libp2p components."""# Peer address TTLspeer_addr_ttl: int=7200# 2 hourstemp_addr_ttl: int=600# 10 minutespermanent_addr_ttl: int=315360000# 10 years# DHT TTLsdht_provider_ttl: int=86400# 24 hoursdht_record_ttl: int=79200# 22 hours# PubSub TTLspubsub_message_ttl: int=7200# 2 hours# Identify TTLsidentify_timeout: int=30# 30 seconds# Trio-specific: Cleanup tasks for proper resource management_cleanup_tasks: List[trio.CancelScope] =Nonedef__post_init__(self):
ifself._cleanup_tasksisNone:
self._cleanup_tasks= []
@classmethoddeffrom_dict(cls, config: dict) ->'TTLConfig':
"""Create TTLConfig from dictionary."""returncls(**{k: vfork, vinconfig.items() ifkincls.__annotations__})
defto_dict(self) ->dict:
"""Convert to dictionary."""return {
field.name: getattr(self, field.name)
forfieldinself.__dataclass_fields__.values()
iffield.name!='_cleanup_tasks'# Exclude internal state
}
asyncdefcleanup(self):
"""Clean up TTL-related resources when cancelled."""fortaskinself._cleanup_tasks:
task.cancel()
self._cleanup_tasks.clear()
defadd_cleanup_task(self, task: trio.CancelScope):
"""Add a cleanup task for proper resource management."""self._cleanup_tasks.append(task)
2. Update Identify Push Implementation
# libp2p/identity/identify_push/identify_push.pyfromlibp2p.config.ttlimportTTLConfigimporttrioclassIdentifyPush:
def__init__(self, host: IHost, ttl_config: Optional[TTLConfig] =None):
self._host=hostself._ttl_config=ttl_configorTTLConfig()
asyncdef_handle_identify_push(self, stream: IStream) ->None:
# Use Trio's timeout mechanism with configurable TTLwithtrio.move_on_after(self._ttl_config.identify_timeout):
# ... existing code ...# Use configurable TTL instead of hardcodedawaitself._host.peerstore.add_addrs(
peer_id, addrs, self._ttl_config.peer_addr_ttl
)
else:
# Handle timeout caselogger.warning("Identify push timed out after %s seconds",
self._ttl_config.identify_timeout)
importwarningsdefadd_addrs(self, peer_id: PeerID, addrs: List[Multiaddr], ttl: int=None):
ifttlisNone:
warnings.warn(
"Using hardcoded TTL. Consider using TTLConfig for better flexibility.",
DeprecationWarning,
stacklevel=2
)
ttl=7200# Default hardcoded value# ... rest of implementation
3. Future Removal
After sufficient migration period, remove hardcoded defaults
Require explicit TTL configuration
Trio-Specific Considerations
Since py-libp2p uses Trio instead of asyncio, the TTL configuration should be designed with Trio's patterns in mind:
Trio's Structured Concurrency
# TTL configuration should work well with Trio's nursery patternasyncdefhandle_identify_push(self, stream: IStream) ->None:
asyncwithtrio.open_nursery() asnursery:
# TTL operations should be cancellablenursery.start_soon(self._process_with_ttl, stream)
Trio's Cancellation Handling
# TTL operations should respect Trio's cancellationasyncdef_process_with_ttl(self, stream: IStream) ->None:
try:
# Use configurable TTL with proper cancellationawaitself._host.peerstore.add_addrs(
peer_id, addrs, self._ttl_config.peer_addr_ttl
)
excepttrio.Cancelled:
# Clean up TTL-related resourcesraise
Trio's Resource Management
# TTL configuration should integrate with Trio's resource managementclassTTLConfig:
def__init__(self, **kwargs):
# ... TTL valuesself._cleanup_tasks: List[trio.CancelScope] = []
asyncdefcleanup(self):
"""Clean up TTL-related resources when cancelled."""fortaskinself._cleanup_tasks:
task.cancel()
Trio's Timeout Handling
# TTL operations should use Trio's timeout mechanismsasyncdef_handle_with_ttl_timeout(self, stream: IStream) ->None:
withtrio.move_on_after(self._ttl_config.identify_timeout):
# TTL-based operations with proper timeout handlingawaitself._process_identify_push(stream)
else:
# Handle timeout caselogger.warning("Identify push timed out after %s seconds",
self._ttl_config.identify_timeout)
Trio's Testing Patterns
# TTL configuration should work well with Trio's testingasyncdeftest_ttl_configuration():
ttl_config=TTLConfig(peer_addr_ttl=1) # 1 second for testingasyncwithtrio.open_nursery() asnursery:
# Test TTL behavior with Trio's structured concurrencynursery.start_soon(test_ttl_expiration, ttl_config)
Real-World Example: Trio's Gradual Migration
Trio itself used gradual migration successfully for breaking changes:
Phase 1: Add new API
# Trio 0.10importtrio# Old way (still works)asyncwithtrio.open_nursery() asnursery:
nursery.start_soon(coro)
# New way (recommended)asyncwithtrio.open_nursery() asnursery:
nursery.start_soon(coro)
Phase 2: Deprecation warnings
# Trio 0.15defstart_soon(self, fn, *args):
warnings.warn(
"start_soon() is deprecated, use start() for better error handling",
DeprecationWarning
)
# ... implementation
Phase 3: Full migration
# Trio 0.20+# start_soon() removed, only start() available
Conclusion
Implementing configurable TTL values will significantly improve py-libp2p's flexibility and align it with Go libp2p's best practices. The proposed solution provides:
Backward compatibility with existing code
Flexibility for different use cases
Consistency across components
Maintainability for future development
This change addresses a fundamental architectural issue and brings py-libp2p closer to production-ready status.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
Issue: Configurable TTL Values in py-libp2p
Problem Statement
The current py-libp2p implementation uses hardcoded TTL (Time To Live) values throughout the codebase, which is not a good practice for several reasons:
Current State Analysis
Hardcoded TTL Values Found
libp2p/identity/identify_push/identify_push.py
libp2p/pubsub/utils.py
libp2p/kad_dht/utils.py
libp2p/kad_dht/utils.py
Issues with Current Approach
Problems:
Go libp2p Best Practices
Go libp2p implements a well-structured, configurable TTL system:
1. Defined TTL Constants
2. Configurable Options
3. Context-Aware TTL Selection
Recommended Solution
1. Create TTL Configuration Module
2. Update Identify Push Implementation
3. Update Other Components
4. Host Configuration Integration
Implementation Plan
Phase 1: Core Infrastructure
TTLConfig
dataclassPhase 2: Component Updates
IdentifyPush
to use configurable TTLPubSub
utilitiesDHT
utilitiesHost
class to accept TTL configPhase 3: Testing & Documentation
Benefits of This Approach
✅ Flexibility
✅ Consistency
✅ Maintainability
✅ Testability
✅ Backward Compatibility
Usage Examples
Basic Usage (Default TTLs)
Custom TTL Configuration
Environment-Specific Configuration
Migration Strategy
1. Gradual Migration
2. Deprecation Warning
3. Future Removal
Trio-Specific Considerations
Since py-libp2p uses Trio instead of asyncio, the TTL configuration should be designed with Trio's patterns in mind:
Trio's Structured Concurrency
Trio's Cancellation Handling
Trio's Resource Management
Trio's Timeout Handling
Trio's Testing Patterns
Real-World Example: Trio's Gradual Migration
Trio itself used gradual migration successfully for breaking changes:
Phase 1: Add new API
Phase 2: Deprecation warnings
Phase 3: Full migration
Conclusion
Implementing configurable TTL values will significantly improve py-libp2p's flexibility and align it with Go libp2p's best practices. The proposed solution provides:
This change addresses a fundamental architectural issue and brings py-libp2p closer to production-ready status.
Beta Was this translation helpful? Give feedback.
All reactions