489 lines
20 KiB
Markdown
489 lines
20 KiB
Markdown
# MY Network v3.0 - Система версионирования и совместимости
|
||
|
||
## 🏷️ Семантическое версионирование
|
||
|
||
MY Network использует семантическое версионирование в формате `MAJOR.MINOR.PATCH`:
|
||
|
||
- **MAJOR**: Критические изменения протокола, несовместимые изменения
|
||
- **MINOR**: Новая функциональность, обратно совместимая
|
||
- **PATCH**: Исправления ошибок, совместимые изменения
|
||
|
||
### Примеры версий
|
||
- `3.0.0` - Основная версия с децентрализованной архитектурой
|
||
- `3.1.0` - Добавление новых функций синхронизации
|
||
- `3.1.2` - Исправление ошибок в синхронизации
|
||
|
||
## 🔒 Правила совместимости
|
||
|
||
### Критические ограничения (MAJOR версии)
|
||
|
||
```python
|
||
class VersionCompatibility:
|
||
"""Система проверки совместимости версий нод"""
|
||
|
||
def __init__(self, current_version: str):
|
||
self.current_version = self.parse_version(current_version)
|
||
|
||
def parse_version(self, version_string: str) -> dict:
|
||
"""Парсинг версии в структурированный формат"""
|
||
try:
|
||
major, minor, patch = version_string.split('.')
|
||
return {
|
||
"major": int(major),
|
||
"minor": int(minor),
|
||
"patch": int(patch),
|
||
"string": version_string
|
||
}
|
||
except ValueError:
|
||
raise ValueError(f"Invalid version format: {version_string}")
|
||
|
||
def check_compatibility(self, peer_version: str) -> dict:
|
||
"""
|
||
Проверка совместимости с версией пира
|
||
|
||
Returns:
|
||
dict: {
|
||
"compatible": bool,
|
||
"level": "compatible|warning|blocked",
|
||
"message": str,
|
||
"allow_connection": bool
|
||
}
|
||
"""
|
||
peer_ver = self.parse_version(peer_version)
|
||
current_ver = self.current_version
|
||
|
||
# Проверка MAJOR версии
|
||
if peer_ver["major"] != current_ver["major"]:
|
||
return {
|
||
"compatible": False,
|
||
"level": "blocked",
|
||
"message": f"Incompatible major version: {peer_version} vs {current_ver['string']}. Connection blocked.",
|
||
"allow_connection": False
|
||
}
|
||
|
||
# Проверка MINOR версии
|
||
if peer_ver["minor"] != current_ver["minor"]:
|
||
newer_version = peer_ver if peer_ver["minor"] > current_ver["minor"] else current_ver
|
||
older_version = peer_ver if peer_ver["minor"] < current_ver["minor"] else current_ver
|
||
|
||
return {
|
||
"compatible": True,
|
||
"level": "warning",
|
||
"message": f"Different minor version: {peer_version} vs {current_ver['string']}. Some features may be unavailable.",
|
||
"allow_connection": True,
|
||
"recommendation": f"Consider updating to v{newer_version['major']}.{newer_version['minor']}.x"
|
||
}
|
||
|
||
# PATCH различия - полная совместимость
|
||
if peer_ver["patch"] != current_ver["patch"]:
|
||
return {
|
||
"compatible": True,
|
||
"level": "compatible",
|
||
"message": f"Compatible versions: {peer_version} vs {current_ver['string']}",
|
||
"allow_connection": True
|
||
}
|
||
|
||
# Идентичные версии
|
||
return {
|
||
"compatible": True,
|
||
"level": "compatible",
|
||
"message": f"Identical versions: {peer_version}",
|
||
"allow_connection": True
|
||
}
|
||
```
|
||
|
||
### Матрица совместимости
|
||
|
||
| Peer Version | Current Version | Result | Action |
|
||
|--------------|-----------------|--------|---------|
|
||
| `3.0.x` | `3.0.x` | ✅ Compatible | Allow connection |
|
||
| `3.1.x` | `3.0.x` | ⚠️ Warning | Allow with warning |
|
||
| `3.0.x` | `3.1.x` | ⚠️ Warning | Allow with warning |
|
||
| `4.0.x` | `3.x.x` | ❌ Blocked | Reject connection |
|
||
| `2.x.x` | `3.x.x` | ❌ Blocked | Reject connection |
|
||
|
||
## 🤝 Протокол handshake с проверкой версий
|
||
|
||
### Расширенный handshake
|
||
|
||
```python
|
||
class VersionAwareHandshake:
|
||
"""Handshake с проверкой версий"""
|
||
|
||
async def perform_handshake(self, peer_connection: PeerConnection) -> bool:
|
||
"""Выполнение handshake с проверкой совместимости версий"""
|
||
|
||
# Отправка handshake с информацией о версии
|
||
handshake_msg = {
|
||
"type": "handshake",
|
||
"node_id": self.node_id,
|
||
"public_key": self.public_key_hex,
|
||
"version": {
|
||
"protocol": MY_NETWORK_VERSION,
|
||
"node": NODE_VERSION,
|
||
"features": self.get_supported_features(),
|
||
"capabilities": self.get_node_capabilities()
|
||
},
|
||
"timestamp": datetime.utcnow().isoformat()
|
||
}
|
||
|
||
# Подписание сообщения
|
||
handshake_msg["signature"] = await self.sign_message(handshake_msg)
|
||
|
||
# Отправка handshake
|
||
await peer_connection.send_message(handshake_msg)
|
||
|
||
# Получение ответа
|
||
response = await peer_connection.receive_message(timeout=30)
|
||
|
||
if response.get("type") != "handshake_response":
|
||
logger.error("Invalid handshake response type")
|
||
return False
|
||
|
||
# Проверка версии пира
|
||
peer_version = response.get("version", {}).get("protocol")
|
||
if not peer_version:
|
||
logger.error("Peer did not provide version information")
|
||
return False
|
||
|
||
# Проверка совместимости
|
||
compatibility = self.version_checker.check_compatibility(peer_version)
|
||
|
||
if not compatibility["allow_connection"]:
|
||
logger.error(f"Version incompatibility: {compatibility['message']}")
|
||
await peer_connection.send_message({
|
||
"type": "handshake_error",
|
||
"reason": "version_incompatible",
|
||
"message": compatibility["message"]
|
||
})
|
||
return False
|
||
|
||
# Логирование предупреждений
|
||
if compatibility["level"] == "warning":
|
||
logger.warning(f"Version compatibility warning: {compatibility['message']}")
|
||
|
||
# Отправка предупреждения пиру
|
||
await peer_connection.send_message({
|
||
"type": "version_warning",
|
||
"message": compatibility["message"],
|
||
"recommendation": compatibility.get("recommendation")
|
||
})
|
||
|
||
# Сохранение информации о версии пира
|
||
peer_connection.version_info = response.get("version")
|
||
peer_connection.compatibility = compatibility
|
||
|
||
logger.info(f"Handshake successful with peer {response.get('node_id')} (v{peer_version})")
|
||
return True
|
||
|
||
def get_supported_features(self) -> List[str]:
|
||
"""Получение списка поддерживаемых функций"""
|
||
return [
|
||
"content_sync",
|
||
"p2p_discovery",
|
||
"content_filtering",
|
||
"version_negotiation",
|
||
"encrypted_transport"
|
||
]
|
||
|
||
def get_node_capabilities(self) -> dict:
|
||
"""Получение возможностей ноды"""
|
||
return {
|
||
"max_peers": self.config.max_connections,
|
||
"storage_capacity": self.get_available_storage(),
|
||
"node_type": self.config.node_type,
|
||
"content_types": self.get_supported_content_types()
|
||
}
|
||
```
|
||
|
||
## 📋 Версионная информация ноды
|
||
|
||
### API эндпоинт для версии
|
||
|
||
```python
|
||
@app.route('/api/v1/system/version', methods=['GET'])
|
||
async def get_version_info(request):
|
||
"""Получение информации о версии ноды"""
|
||
|
||
return response.json({
|
||
"version": {
|
||
"protocol": MY_NETWORK_VERSION,
|
||
"node": NODE_VERSION,
|
||
"api": API_VERSION,
|
||
"build": BUILD_VERSION,
|
||
"build_date": BUILD_DATE
|
||
},
|
||
"compatibility": {
|
||
"min_protocol_version": "3.0.0",
|
||
"max_protocol_version": "3.9.9",
|
||
"deprecated_versions": ["2.x.x"],
|
||
"supported_features": [
|
||
"content_sync",
|
||
"p2p_discovery",
|
||
"content_filtering",
|
||
"version_negotiation"
|
||
]
|
||
},
|
||
"node_info": {
|
||
"node_id": node_service.node_id,
|
||
"node_type": node_service.config.node_type,
|
||
"uptime": node_service.get_uptime_seconds(),
|
||
"capabilities": node_service.get_node_capabilities()
|
||
}
|
||
})
|
||
|
||
@app.route('/api/v1/system/compatibility', methods=['POST'])
|
||
async def check_version_compatibility(request):
|
||
"""Проверка совместимости с другой версией"""
|
||
|
||
data = request.json
|
||
peer_version = data.get("version")
|
||
|
||
if not peer_version:
|
||
return response.json({"error": "Version is required"}, status=400)
|
||
|
||
try:
|
||
compatibility = version_checker.check_compatibility(peer_version)
|
||
return response.json(compatibility)
|
||
except ValueError as e:
|
||
return response.json({"error": str(e)}, status=400)
|
||
```
|
||
|
||
## 🔄 Автоматическое обновление
|
||
|
||
### Проверка обновлений
|
||
|
||
```python
|
||
class UpdateChecker:
|
||
"""Система проверки и уведомления об обновлениях"""
|
||
|
||
def __init__(self, current_version: str, update_url: str):
|
||
self.current_version = current_version
|
||
self.update_url = update_url
|
||
self.last_check = None
|
||
|
||
async def check_for_updates(self) -> dict:
|
||
"""Проверка доступных обновлений"""
|
||
|
||
try:
|
||
# Запрос информации о последней версии
|
||
async with aiohttp.ClientSession() as session:
|
||
async with session.get(f"{self.update_url}/latest-version") as response:
|
||
if response.status == 200:
|
||
data = await response.json()
|
||
latest_version = data.get("version")
|
||
|
||
if latest_version:
|
||
update_info = self._compare_versions(latest_version)
|
||
self.last_check = datetime.utcnow()
|
||
return update_info
|
||
|
||
except Exception as e:
|
||
logger.error(f"Failed to check for updates: {e}")
|
||
|
||
return {"update_available": False, "error": "Failed to check updates"}
|
||
|
||
def _compare_versions(self, latest_version: str) -> dict:
|
||
"""Сравнение текущей и последней версии"""
|
||
|
||
current = self._parse_version(self.current_version)
|
||
latest = self._parse_version(latest_version)
|
||
|
||
if latest["major"] > current["major"]:
|
||
return {
|
||
"update_available": True,
|
||
"update_type": "major",
|
||
"current_version": self.current_version,
|
||
"latest_version": latest_version,
|
||
"critical": True,
|
||
"message": "Major update available with breaking changes"
|
||
}
|
||
|
||
elif latest["minor"] > current["minor"]:
|
||
return {
|
||
"update_available": True,
|
||
"update_type": "minor",
|
||
"current_version": self.current_version,
|
||
"latest_version": latest_version,
|
||
"critical": False,
|
||
"message": "Minor update available with new features"
|
||
}
|
||
|
||
elif latest["patch"] > current["patch"]:
|
||
return {
|
||
"update_available": True,
|
||
"update_type": "patch",
|
||
"current_version": self.current_version,
|
||
"latest_version": latest_version,
|
||
"critical": False,
|
||
"message": "Patch update available with bug fixes"
|
||
}
|
||
|
||
return {
|
||
"update_available": False,
|
||
"current_version": self.current_version,
|
||
"latest_version": latest_version,
|
||
"message": "You are running the latest version"
|
||
}
|
||
|
||
async def get_update_recommendations(self) -> List[str]:
|
||
"""Получение рекомендаций по обновлению"""
|
||
|
||
update_info = await self.check_for_updates()
|
||
|
||
if not update_info.get("update_available"):
|
||
return ["Your node is up to date"]
|
||
|
||
recommendations = []
|
||
|
||
if update_info.get("critical"):
|
||
recommendations.append("🔴 Critical update available - update immediately for compatibility")
|
||
|
||
if update_info.get("update_type") == "major":
|
||
recommendations.append("⚠️ Major version update - review breaking changes before updating")
|
||
recommendations.append("📋 Backup your data before major version updates")
|
||
|
||
elif update_info.get("update_type") == "minor":
|
||
recommendations.append("✨ New features available in minor update")
|
||
recommendations.append("🔄 Safe to update - backwards compatible")
|
||
|
||
elif update_info.get("update_type") == "patch":
|
||
recommendations.append("🐛 Bug fixes available - recommended to update")
|
||
|
||
return recommendations
|
||
```
|
||
|
||
## 📊 Мониторинг версий в сети
|
||
|
||
### Статистика версий
|
||
|
||
```python
|
||
class NetworkVersionMonitor:
|
||
"""Мониторинг версий нод в сети"""
|
||
|
||
def __init__(self):
|
||
self.peer_versions = {}
|
||
|
||
async def track_peer_version(self, peer_id: str, version_info: dict):
|
||
"""Отслеживание версии пира"""
|
||
|
||
self.peer_versions[peer_id] = {
|
||
"version": version_info,
|
||
"last_seen": datetime.utcnow(),
|
||
"compatible": True
|
||
}
|
||
|
||
async def get_network_version_stats(self) -> dict:
|
||
"""Статистика версий в сети"""
|
||
|
||
if not self.peer_versions:
|
||
return {"total_peers": 0, "version_distribution": {}}
|
||
|
||
version_counts = {}
|
||
total_peers = len(self.peer_versions)
|
||
compatible_peers = 0
|
||
|
||
for peer_id, peer_data in self.peer_versions.items():
|
||
version = peer_data["version"]["protocol"]
|
||
version_counts[version] = version_counts.get(version, 0) + 1
|
||
|
||
if peer_data["compatible"]:
|
||
compatible_peers += 1
|
||
|
||
return {
|
||
"total_peers": total_peers,
|
||
"compatible_peers": compatible_peers,
|
||
"compatibility_rate": compatible_peers / total_peers if total_peers > 0 else 0,
|
||
"version_distribution": version_counts,
|
||
"most_common_version": max(version_counts.items(), key=lambda x: x[1])[0] if version_counts else None
|
||
}
|
||
|
||
async def get_outdated_peers(self) -> List[dict]:
|
||
"""Список пиров с устаревшими версиями"""
|
||
|
||
current_major = self._parse_version(MY_NETWORK_VERSION)["major"]
|
||
outdated = []
|
||
|
||
for peer_id, peer_data in self.peer_versions.items():
|
||
peer_version = peer_data["version"]["protocol"]
|
||
peer_major = self._parse_version(peer_version)["major"]
|
||
|
||
if peer_major < current_major:
|
||
outdated.append({
|
||
"peer_id": peer_id,
|
||
"version": peer_version,
|
||
"age": (datetime.utcnow() - peer_data["last_seen"]).total_seconds()
|
||
})
|
||
|
||
return sorted(outdated, key=lambda x: x["age"], reverse=True)
|
||
```
|
||
|
||
## 🚨 Предупреждения и уведомления
|
||
|
||
### Система уведомлений о версиях
|
||
|
||
```python
|
||
class VersionNotificationManager:
|
||
"""Управление уведомлениями о версиях"""
|
||
|
||
async def notify_version_mismatch(self, peer_id: str, peer_version: str, compatibility: dict):
|
||
"""Уведомление о несоответствии версий"""
|
||
|
||
if compatibility["level"] == "blocked":
|
||
logger.error(f"🚫 Connection blocked: Peer {peer_id} version {peer_version} incompatible")
|
||
|
||
# Можно добавить отправку в мониторинг
|
||
await self._send_to_monitoring({
|
||
"type": "version_incompatibility",
|
||
"peer_id": peer_id,
|
||
"peer_version": peer_version,
|
||
"severity": "critical"
|
||
})
|
||
|
||
elif compatibility["level"] == "warning":
|
||
logger.warning(f"⚠️ Version warning: Peer {peer_id} version {peer_version} - {compatibility['message']}")
|
||
|
||
await self._send_to_monitoring({
|
||
"type": "version_warning",
|
||
"peer_id": peer_id,
|
||
"peer_version": peer_version,
|
||
"severity": "warning",
|
||
"recommendation": compatibility.get("recommendation")
|
||
})
|
||
|
||
async def notify_update_available(self, update_info: dict):
|
||
"""Уведомление о доступном обновлении"""
|
||
|
||
if update_info.get("critical"):
|
||
logger.error(f"🔴 Critical update available: {update_info['latest_version']}")
|
||
else:
|
||
logger.info(f"✨ Update available: {update_info['latest_version']}")
|
||
|
||
# Отправка в систему мониторинга
|
||
await self._send_to_monitoring({
|
||
"type": "update_available",
|
||
"current_version": update_info["current_version"],
|
||
"latest_version": update_info["latest_version"],
|
||
"update_type": update_info["update_type"],
|
||
"critical": update_info.get("critical", False)
|
||
})
|
||
```
|
||
|
||
## 📖 API эндпоинты для версионирования
|
||
|
||
```python
|
||
# Информация о версии
|
||
GET /api/v1/system/version # Полная информация о версии
|
||
GET /api/v1/system/compatibility # Информация о совместимости
|
||
POST /api/v1/system/compatibility/check # Проверка совместимости с версией
|
||
|
||
# Обновления
|
||
GET /api/v1/system/updates/check # Проверка доступных обновлений
|
||
GET /api/v1/system/updates/recommendations # Рекомендации по обновлению
|
||
|
||
# Статистика сети
|
||
GET /api/v1/network/versions # Статистика версий в сети
|
||
GET /api/v1/network/compatibility/stats # Статистика совместимости
|
||
```
|
||
|
||
Эта система обеспечивает надежную работу сети при наличии нод с разными версиями, предотвращая проблемы совместимости и обеспечивая плавные обновления. |