20 KiB
20 KiB
MY Network v3.0 - Система версионирования и совместимости
🏷️ Семантическое версионирование
MY Network использует семантическое версионирование в формате MAJOR.MINOR.PATCH:
- MAJOR: Критические изменения протокола, несовместимые изменения
- MINOR: Новая функциональность, обратно совместимая
- PATCH: Исправления ошибок, совместимые изменения
Примеры версий
3.0.0- Основная версия с децентрализованной архитектурой3.1.0- Добавление новых функций синхронизации3.1.2- Исправление ошибок в синхронизации
🔒 Правила совместимости
Критические ограничения (MAJOR версии)
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
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 эндпоинт для версии
@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)
🔄 Автоматическое обновление
Проверка обновлений
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
📊 Мониторинг версий в сети
Статистика версий
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)
🚨 Предупреждения и уведомления
Система уведомлений о версиях
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 эндпоинты для версионирования
# Информация о версии
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 # Статистика совместимости
Эта система обеспечивает надежную работу сети при наличии нод с разными версиями, предотвращая проблемы совместимости и обеспечивая плавные обновления.