fix: replace datetime.UTC with timezone.utc for Python 3.12+ compatibility
Some checks failed
API Endpoint Tests / test-api-endpoints (push) Successful in 22s
Blockchain Synchronization Verification / sync-verification (push) Successful in 3s
CLI Tests / test-cli (push) Failing after 13s
Cross-Chain Functionality Tests / test-cross-chain-sync (push) Failing after 3s
Cross-Chain Functionality Tests / test-cross-chain-transactions (push) Successful in 3s
Cross-Chain Functionality Tests / test-cross-chain-bridge (push) Has been skipped
Cross-Chain Functionality Tests / test-multi-chain-consensus (push) Failing after 3s
Cross-Chain Functionality Tests / aggregate-results (push) Has been skipped
Cross-Node Transaction Testing / transaction-test (push) Successful in 2s
Deploy to Testnet / deploy-testnet (push) Successful in 1m34s
Documentation Validation / validate-docs (push) Failing after 10s
Documentation Validation / validate-policies-strict (push) Successful in 3s
Multi-Node Stress Testing / stress-test (push) Has been cancelled
Node Failover Simulation / failover-test (push) Has been cancelled
Python Tests / test-python (push) Has been cancelled
Integration Tests / test-service-integration (push) Successful in 2m42s
Multi-Chain Island Architecture Tests / test-multi-chain-island (push) Successful in 3s
Multi-Node Blockchain Health Monitoring / health-check (push) Successful in 5s
P2P Network Verification / p2p-verification (push) Successful in 3s
Package Tests / Python package - aitbc-agent-sdk (push) Failing after 33s
Package Tests / Python package - aitbc-core (push) Successful in 17s
Package Tests / Python package - aitbc-crypto (push) Successful in 11s
Security Scanning / security-scan (push) Has been cancelled
Package Tests / Python package - aitbc-sdk (push) Successful in 13s
Package Tests / JavaScript package - aitbc-sdk-js (push) Successful in 9s
Package Tests / JavaScript package - aitbc-token (push) Successful in 17s
Staking Tests / test-staking-service (push) Failing after 6s
Staking Tests / test-staking-integration (push) Has been skipped
Staking Tests / test-staking-contract (push) Has been skipped
Staking Tests / run-staking-test-runner (push) Has been skipped
Some checks failed
API Endpoint Tests / test-api-endpoints (push) Successful in 22s
Blockchain Synchronization Verification / sync-verification (push) Successful in 3s
CLI Tests / test-cli (push) Failing after 13s
Cross-Chain Functionality Tests / test-cross-chain-sync (push) Failing after 3s
Cross-Chain Functionality Tests / test-cross-chain-transactions (push) Successful in 3s
Cross-Chain Functionality Tests / test-cross-chain-bridge (push) Has been skipped
Cross-Chain Functionality Tests / test-multi-chain-consensus (push) Failing after 3s
Cross-Chain Functionality Tests / aggregate-results (push) Has been skipped
Cross-Node Transaction Testing / transaction-test (push) Successful in 2s
Deploy to Testnet / deploy-testnet (push) Successful in 1m34s
Documentation Validation / validate-docs (push) Failing after 10s
Documentation Validation / validate-policies-strict (push) Successful in 3s
Multi-Node Stress Testing / stress-test (push) Has been cancelled
Node Failover Simulation / failover-test (push) Has been cancelled
Python Tests / test-python (push) Has been cancelled
Integration Tests / test-service-integration (push) Successful in 2m42s
Multi-Chain Island Architecture Tests / test-multi-chain-island (push) Successful in 3s
Multi-Node Blockchain Health Monitoring / health-check (push) Successful in 5s
P2P Network Verification / p2p-verification (push) Successful in 3s
Package Tests / Python package - aitbc-agent-sdk (push) Failing after 33s
Package Tests / Python package - aitbc-core (push) Successful in 17s
Package Tests / Python package - aitbc-crypto (push) Successful in 11s
Security Scanning / security-scan (push) Has been cancelled
Package Tests / Python package - aitbc-sdk (push) Successful in 13s
Package Tests / JavaScript package - aitbc-sdk-js (push) Successful in 9s
Package Tests / JavaScript package - aitbc-token (push) Successful in 17s
Staking Tests / test-staking-service (push) Failing after 6s
Staking Tests / test-staking-integration (push) Has been skipped
Staking Tests / test-staking-contract (push) Has been skipped
Staking Tests / run-staking-test-runner (push) Has been skipped
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
"""Miner Registry Implementation"""
|
||||
|
||||
from typing import List, Optional, Dict, Any
|
||||
from datetime import datetime, UTC, timedelta
|
||||
from datetime import datetime, timezone, timedelta
|
||||
from dataclasses import dataclass, field
|
||||
import asyncio
|
||||
|
||||
@@ -22,8 +22,8 @@ class MinerInfo:
|
||||
jobs_completed: int = 0
|
||||
jobs_failed: int = 0
|
||||
uptime_percent: float = 100.0
|
||||
registered_at: datetime = field(default_factory=datetime.now(datetime.UTC))
|
||||
last_heartbeat: datetime = field(default_factory=datetime.now(datetime.UTC))
|
||||
registered_at: datetime = field(default_factory=datetime.now(timezone.utc))
|
||||
last_heartbeat: datetime = field(default_factory=datetime.now(timezone.utc))
|
||||
gpu_utilization: float = 0.0
|
||||
memory_used_gb: float = 0.0
|
||||
|
||||
@@ -43,7 +43,7 @@ class PoolInfo:
|
||||
total_hashrate: float = 0.0
|
||||
jobs_completed_24h: int = 0
|
||||
earnings_24h: float = 0.0
|
||||
created_at: datetime = field(default_factory=datetime.now(datetime.UTC))
|
||||
created_at: datetime = field(default_factory=datetime.now(timezone.utc))
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -55,7 +55,7 @@ class JobAssignment:
|
||||
pool_id: str
|
||||
model: str
|
||||
status: str = "assigned"
|
||||
assigned_at: datetime = field(default_factory=datetime.now(datetime.UTC))
|
||||
assigned_at: datetime = field(default_factory=datetime.now(timezone.utc))
|
||||
deadline: Optional[datetime] = None
|
||||
completed_at: Optional[datetime] = None
|
||||
|
||||
@@ -142,7 +142,7 @@ class MinerRegistry:
|
||||
miner.current_jobs = current_jobs
|
||||
miner.gpu_utilization = gpu_utilization
|
||||
miner.memory_used_gb = memory_used_gb
|
||||
miner.last_heartbeat = datetime.now(datetime.UTC)
|
||||
miner.last_heartbeat = datetime.now(timezone.utc)
|
||||
|
||||
async def update_capabilities(self, miner_id: str, capabilities: List[str]):
|
||||
"""Update miner capabilities."""
|
||||
@@ -271,7 +271,7 @@ class MinerRegistry:
|
||||
if job_id in self._jobs:
|
||||
job = self._jobs[job_id]
|
||||
job.status = status
|
||||
job.completed_at = datetime.now(datetime.UTC)
|
||||
job.completed_at = datetime.now(timezone.utc)
|
||||
|
||||
if miner_id in self._miners:
|
||||
miner = self._miners[miner_id]
|
||||
@@ -314,7 +314,7 @@ class MinerRegistry:
|
||||
# Update job
|
||||
job.miner_id = new_miner_id
|
||||
job.status = "assigned"
|
||||
job.assigned_at = datetime.now(datetime.UTC)
|
||||
job.assigned_at = datetime.now(timezone.utc)
|
||||
|
||||
# Update new miner
|
||||
if new_miner_id in self._miners:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Health check routes for Pool Hub"""
|
||||
|
||||
from fastapi import APIRouter
|
||||
from datetime import datetime, UTC
|
||||
from datetime import datetime, timezone
|
||||
from sqlalchemy import text
|
||||
|
||||
router = APIRouter(tags=["health"])
|
||||
@@ -13,7 +13,7 @@ async def health_check():
|
||||
return {
|
||||
"status": "ok",
|
||||
"service": "pool-hub",
|
||||
"timestamp": datetime.now(datetime.UTC).isoformat(),
|
||||
"timestamp": datetime.now(timezone.utc).isoformat(),
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ async def readiness_check():
|
||||
return {
|
||||
"ready": all_ready,
|
||||
"checks": checks,
|
||||
"timestamp": datetime.now(datetime.UTC).isoformat(),
|
||||
"timestamp": datetime.now(timezone.utc).isoformat(),
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from fastapi import APIRouter, HTTPException, Depends, Query
|
||||
from typing import List, Optional
|
||||
from datetime import datetime, UTC
|
||||
from datetime import datetime, timezone
|
||||
from pydantic import BaseModel
|
||||
|
||||
from ..registry import MinerRegistry
|
||||
@@ -86,7 +86,7 @@ async def assign_job(
|
||||
job_id=job.job_id,
|
||||
miner_id=best_miner.miner_id,
|
||||
pool_id=best_miner.pool_id,
|
||||
assigned_at=datetime.now(datetime.UTC),
|
||||
assigned_at=datetime.now(timezone.utc),
|
||||
deadline=job.deadline
|
||||
)
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from typing import List, Dict, Any, Optional
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, UTC, timedelta
|
||||
from datetime import datetime, timezone, timedelta
|
||||
import math
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ class ScoringEngine:
|
||||
success_rate = 100.0 # New miners start with perfect score
|
||||
|
||||
# Heartbeat freshness penalty
|
||||
heartbeat_age = (datetime.now(datetime.UTC) - miner.last_heartbeat).total_seconds()
|
||||
heartbeat_age = (datetime.now(timezone.utc) - miner.last_heartbeat).total_seconds()
|
||||
if heartbeat_age > 300: # 5 minutes
|
||||
freshness_penalty = min(20, heartbeat_age / 60)
|
||||
else:
|
||||
@@ -137,7 +137,7 @@ class ScoringEngine:
|
||||
weight_total = 0
|
||||
|
||||
for record in history:
|
||||
age_days = (datetime.now(datetime.UTC) - record["timestamp"]).days
|
||||
age_days = (datetime.now(timezone.utc) - record["timestamp"]).days
|
||||
weight = math.exp(-age_days / self.DECAY_HALF_LIFE_DAYS)
|
||||
|
||||
if record["success"]:
|
||||
@@ -153,7 +153,7 @@ class ScoringEngine:
|
||||
|
||||
def _get_hours_active(self, miner) -> float:
|
||||
"""Get hours since miner registered."""
|
||||
delta = datetime.now(datetime.UTC) - miner.registered_at
|
||||
delta = datetime.now(timezone.utc) - miner.registered_at
|
||||
return max(1, delta.total_seconds() / 3600)
|
||||
|
||||
def _parse_memory(self, memory_str: str) -> float:
|
||||
@@ -204,7 +204,7 @@ class ScoringEngine:
|
||||
self._history[miner_id] = []
|
||||
|
||||
self._history[miner_id].append({
|
||||
"timestamp": datetime.now(datetime.UTC),
|
||||
"timestamp": datetime.now(timezone.utc),
|
||||
"success": True,
|
||||
"metrics": metrics or {}
|
||||
})
|
||||
@@ -219,7 +219,7 @@ class ScoringEngine:
|
||||
self._history[miner_id] = []
|
||||
|
||||
self._history[miner_id].append({
|
||||
"timestamp": datetime.now(datetime.UTC),
|
||||
"timestamp": datetime.now(timezone.utc),
|
||||
"success": False,
|
||||
"error": error
|
||||
})
|
||||
|
||||
@@ -3,7 +3,7 @@ SLA and Billing API Endpoints for Pool-Hub
|
||||
Provides endpoints for SLA metrics, capacity planning, and billing integration.
|
||||
"""
|
||||
|
||||
from datetime import datetime, UTC, timedelta
|
||||
from datetime import datetime, timezone, timedelta
|
||||
from typing import Dict, List, Optional, Any
|
||||
from decimal import Decimal
|
||||
|
||||
@@ -165,7 +165,7 @@ async def get_capacity_snapshots(
|
||||
):
|
||||
"""Get capacity planning snapshots"""
|
||||
try:
|
||||
cutoff = datetime.now(datetime.UTC) - timedelta(hours=hours)
|
||||
cutoff = datetime.now(timezone.utc) - timedelta(hours=hours)
|
||||
stmt = (
|
||||
db.query(CapacitySnapshot)
|
||||
.filter(CapacitySnapshot.timestamp >= cutoff)
|
||||
@@ -236,7 +236,7 @@ async def configure_capacity_alerts(
|
||||
return {
|
||||
"status": "configured",
|
||||
"alert_config": alert_config,
|
||||
"timestamp": datetime.now(datetime.UTC).isoformat(),
|
||||
"timestamp": datetime.now(timezone.utc).isoformat(),
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"Error configuring capacity alerts: {e}")
|
||||
@@ -270,7 +270,7 @@ async def sync_billing_usage(
|
||||
try:
|
||||
if request.miner_id:
|
||||
# Sync specific miner
|
||||
end_date = datetime.now(datetime.UTC)
|
||||
end_date = datetime.now(timezone.utc)
|
||||
start_date = end_date - timedelta(hours=request.hours_back)
|
||||
result = await billing_integration.sync_miner_usage(
|
||||
miner_id=request.miner_id, start_date=start_date, end_date=end_date
|
||||
@@ -350,7 +350,7 @@ async def get_sla_status(db: Session = Depends(get_db)):
|
||||
"status": status,
|
||||
"active_violations": len(active_violations),
|
||||
"recent_metrics_count": len(recent_metrics),
|
||||
"timestamp": datetime.now(datetime.UTC).isoformat(),
|
||||
"timestamp": datetime.now(timezone.utc).isoformat(),
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting SLA status: {e}")
|
||||
|
||||
@@ -40,7 +40,7 @@ class Miner(Base):
|
||||
miner_id: Mapped[str] = mapped_column(String(64), primary_key=True)
|
||||
api_key_hash: Mapped[str] = mapped_column(String(128), nullable=False)
|
||||
created_at: Mapped[dt.datetime] = mapped_column(
|
||||
DateTime(timezone=True), default=dt.datetime.now(datetime.UTC)
|
||||
DateTime(timezone=True), default=dt.datetime.now(timezone.utc)
|
||||
)
|
||||
last_seen_at: Mapped[Optional[dt.datetime]] = mapped_column(DateTime(timezone=True))
|
||||
addr: Mapped[str] = mapped_column(String(256))
|
||||
@@ -78,7 +78,7 @@ class MinerStatus(Base):
|
||||
uptime_pct: Mapped[Optional[float]] = mapped_column(Float) # SLA metric
|
||||
last_heartbeat_at: Mapped[Optional[dt.datetime]] = mapped_column(DateTime(timezone=True))
|
||||
updated_at: Mapped[dt.datetime] = mapped_column(
|
||||
DateTime(timezone=True), default=dt.datetime.now(datetime.UTC), onupdate=dt.datetime.now(datetime.UTC)
|
||||
DateTime(timezone=True), default=dt.datetime.now(timezone.utc), onupdate=dt.datetime.now(timezone.utc)
|
||||
)
|
||||
|
||||
miner: Mapped[Miner] = relationship(back_populates="status")
|
||||
@@ -95,7 +95,7 @@ class MatchRequest(Base):
|
||||
hints: Mapped[Dict[str, object]] = mapped_column(JSON, default=dict)
|
||||
top_k: Mapped[int] = mapped_column(Integer, default=1)
|
||||
created_at: Mapped[dt.datetime] = mapped_column(
|
||||
DateTime(timezone=True), default=dt.datetime.now(datetime.UTC)
|
||||
DateTime(timezone=True), default=dt.datetime.now(timezone.utc)
|
||||
)
|
||||
|
||||
results: Mapped[List["MatchResult"]] = relationship(
|
||||
@@ -119,7 +119,7 @@ class MatchResult(Base):
|
||||
price: Mapped[Optional[float]] = mapped_column(Float)
|
||||
|
||||
created_at: Mapped[dt.datetime] = mapped_column(
|
||||
DateTime(timezone=True), default=dt.datetime.now(datetime.UTC)
|
||||
DateTime(timezone=True), default=dt.datetime.now(timezone.utc)
|
||||
)
|
||||
|
||||
request: Mapped[MatchRequest] = relationship(back_populates="results")
|
||||
@@ -140,7 +140,7 @@ class Feedback(Base):
|
||||
fail_code: Mapped[Optional[str]] = mapped_column(String(64))
|
||||
tokens_spent: Mapped[Optional[float]] = mapped_column(Float)
|
||||
created_at: Mapped[dt.datetime] = mapped_column(
|
||||
DateTime(timezone=True), default=dt.datetime.now(datetime.UTC)
|
||||
DateTime(timezone=True), default=dt.datetime.now(timezone.utc)
|
||||
)
|
||||
|
||||
miner: Mapped[Miner] = relationship(back_populates="feedback")
|
||||
@@ -164,10 +164,10 @@ class ServiceConfig(Base):
|
||||
capabilities: Mapped[List[str]] = mapped_column(JSON, default=list)
|
||||
max_concurrent: Mapped[int] = mapped_column(Integer, default=1)
|
||||
created_at: Mapped[dt.datetime] = mapped_column(
|
||||
DateTime(timezone=True), default=dt.datetime.now(datetime.UTC)
|
||||
DateTime(timezone=True), default=dt.datetime.now(timezone.utc)
|
||||
)
|
||||
updated_at: Mapped[dt.datetime] = mapped_column(
|
||||
DateTime(timezone=True), default=dt.datetime.now(datetime.UTC), onupdate=dt.datetime.now(datetime.UTC)
|
||||
DateTime(timezone=True), default=dt.datetime.now(timezone.utc), onupdate=dt.datetime.now(timezone.utc)
|
||||
)
|
||||
|
||||
# Add unique constraint for miner_id + service_type
|
||||
@@ -192,7 +192,7 @@ class SLAMetric(Base):
|
||||
threshold: Mapped[float] = mapped_column(Float, nullable=False)
|
||||
is_violation: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
timestamp: Mapped[dt.datetime] = mapped_column(
|
||||
DateTime(timezone=True), default=dt.datetime.now(datetime.UTC)
|
||||
DateTime(timezone=True), default=dt.datetime.now(timezone.utc)
|
||||
)
|
||||
meta_data: Mapped[Dict[str, str]] = mapped_column(JSON, default=dict)
|
||||
|
||||
@@ -217,7 +217,7 @@ class SLAViolation(Base):
|
||||
violation_duration_ms: Mapped[Optional[int]] = mapped_column(Integer)
|
||||
resolved_at: Mapped[Optional[dt.datetime]] = mapped_column(DateTime(timezone=True))
|
||||
created_at: Mapped[dt.datetime] = mapped_column(
|
||||
DateTime(timezone=True), default=dt.datetime.now(datetime.UTC)
|
||||
DateTime(timezone=True), default=dt.datetime.now(timezone.utc)
|
||||
)
|
||||
meta_data: Mapped[Dict[str, str]] = mapped_column(JSON, default=dict)
|
||||
|
||||
@@ -241,6 +241,6 @@ class CapacitySnapshot(Base):
|
||||
recommended_scaling: Mapped[str] = mapped_column(String(32), nullable=False)
|
||||
scaling_reason: Mapped[str] = mapped_column(Text)
|
||||
timestamp: Mapped[dt.datetime] = mapped_column(
|
||||
DateTime(timezone=True), default=dt.datetime.now(datetime.UTC)
|
||||
DateTime(timezone=True), default=dt.datetime.now(timezone.utc)
|
||||
)
|
||||
meta_data: Mapped[Dict[str, Any]] = mapped_column(JSON, default=dict)
|
||||
|
||||
@@ -40,7 +40,7 @@ class FeedbackRepository:
|
||||
latency_ms=latency_ms,
|
||||
fail_code=fail_code,
|
||||
tokens_spent=tokens_spent,
|
||||
created_at=dt.datetime.now(datetime.UTC),
|
||||
created_at=dt.datetime.now(timezone.utc),
|
||||
)
|
||||
self._session.add(feedback)
|
||||
await self._session.flush()
|
||||
|
||||
@@ -34,7 +34,7 @@ class MatchRepository:
|
||||
requirements=requirements,
|
||||
hints=hints or {},
|
||||
top_k=top_k,
|
||||
created_at=dt.datetime.now(datetime.UTC),
|
||||
created_at=dt.datetime.now(timezone.utc),
|
||||
)
|
||||
self._session.add(request)
|
||||
await self._session.flush()
|
||||
@@ -58,7 +58,7 @@ class MatchRepository:
|
||||
publish: bool = True,
|
||||
) -> List[MatchResult]:
|
||||
results: List[MatchResult] = []
|
||||
created_at = dt.datetime.now(datetime.UTC)
|
||||
created_at = dt.datetime.now(timezone.utc)
|
||||
for candidate in candidates:
|
||||
result = MatchResult(
|
||||
request_id=request_id,
|
||||
|
||||
@@ -69,7 +69,7 @@ class MinerRepository:
|
||||
miner.capabilities = capabilities
|
||||
miner.region = region
|
||||
|
||||
miner.last_seen_at = dt.datetime.now(datetime.UTC)
|
||||
miner.last_seen_at = dt.datetime.now(timezone.utc)
|
||||
|
||||
await self._session.flush()
|
||||
await self._sync_miner_to_redis(miner_id)
|
||||
@@ -97,7 +97,7 @@ class MinerRepository:
|
||||
"avg_latency_ms": avg_latency_ms,
|
||||
"temp_c": temp_c,
|
||||
"mem_free_gb": mem_free_gb,
|
||||
"updated_at": dt.datetime.now(datetime.UTC),
|
||||
"updated_at": dt.datetime.now(timezone.utc),
|
||||
}.items()
|
||||
if v is not None
|
||||
}
|
||||
@@ -107,7 +107,7 @@ class MinerRepository:
|
||||
|
||||
miner = await self._session.get(Miner, miner_id)
|
||||
if miner:
|
||||
miner.last_seen_at = dt.datetime.now(datetime.UTC)
|
||||
miner.last_seen_at = dt.datetime.now(timezone.utc)
|
||||
await self._session.flush()
|
||||
await self._sync_miner_to_redis(miner_id)
|
||||
|
||||
@@ -115,7 +115,7 @@ class MinerRepository:
|
||||
miner = await self._session.get(Miner, miner_id)
|
||||
if miner is None:
|
||||
return
|
||||
miner.last_seen_at = dt.datetime.now(datetime.UTC)
|
||||
miner.last_seen_at = dt.datetime.now(timezone.utc)
|
||||
await self._session.flush()
|
||||
await self._sync_miner_to_redis(miner_id)
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ Integrates pool-hub usage data with coordinator-api's billing system.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from datetime import datetime, UTC, timedelta
|
||||
from datetime import datetime, timezone, timedelta
|
||||
from decimal import Decimal
|
||||
from typing import Dict, List, Optional, Any
|
||||
|
||||
@@ -76,7 +76,7 @@ class BillingIntegration:
|
||||
"unit_price": float(unit_price),
|
||||
"total_amount": float(total_cost),
|
||||
"currency": "USD",
|
||||
"timestamp": datetime.now(datetime.UTC).isoformat(),
|
||||
"timestamp": datetime.now(timezone.utc).isoformat(),
|
||||
"metadata": metadata or {},
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ class BillingIntegration:
|
||||
) -> Dict[str, Any]:
|
||||
"""Sync usage data for all miners to coordinator-api billing"""
|
||||
|
||||
end_date = datetime.now(datetime.UTC)
|
||||
end_date = datetime.now(timezone.utc)
|
||||
start_date = end_date - timedelta(hours=hours_back)
|
||||
|
||||
# Get all miners
|
||||
|
||||
@@ -4,7 +4,7 @@ Collects and tracks SLA metrics for miners including uptime, response time, job
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from datetime import datetime, UTC, timedelta
|
||||
from datetime import datetime, timezone, timedelta
|
||||
from decimal import Decimal
|
||||
from typing import Dict, List, Optional, Any
|
||||
|
||||
@@ -57,7 +57,7 @@ class SLACollector:
|
||||
metric_value=metric_value,
|
||||
threshold=threshold,
|
||||
is_violation=is_violation,
|
||||
timestamp=datetime.now(datetime.UTC),
|
||||
timestamp=datetime.now(timezone.utc),
|
||||
meta_data=metadata or {},
|
||||
)
|
||||
|
||||
@@ -90,7 +90,7 @@ class SLACollector:
|
||||
# Calculate uptime based on last heartbeat
|
||||
if miner_status.last_heartbeat_at:
|
||||
time_since_heartbeat = (
|
||||
datetime.now(datetime.UTC) - miner_status.last_heartbeat_at
|
||||
datetime.now(timezone.utc) - miner_status.last_heartbeat_at
|
||||
).total_seconds()
|
||||
|
||||
# Consider miner down if no heartbeat for 5 minutes
|
||||
@@ -153,7 +153,7 @@ class SLACollector:
|
||||
stmt = (
|
||||
select(Feedback)
|
||||
.where(Feedback.miner_id == miner_id)
|
||||
.where(Feedback.created_at >= datetime.now(datetime.UTC) - timedelta(days=7))
|
||||
.where(Feedback.created_at >= datetime.now(timezone.utc) - timedelta(days=7))
|
||||
.order_by(Feedback.created_at.desc())
|
||||
.limit(100)
|
||||
)
|
||||
@@ -206,7 +206,7 @@ class SLACollector:
|
||||
forecast_capacity=total_miners, # Would be calculated from forecasting
|
||||
recommended_scaling="stable",
|
||||
scaling_reason="Capacity within normal range",
|
||||
timestamp=datetime.now(datetime.UTC),
|
||||
timestamp=datetime.now(timezone.utc),
|
||||
meta_data={"method": "real_time_collection"},
|
||||
)
|
||||
|
||||
@@ -266,7 +266,7 @@ class SLACollector:
|
||||
stmt = (
|
||||
select(func.count(SLAViolation.id))
|
||||
.where(SLAViolation.resolved_at.is_(None))
|
||||
.where(SLAViolation.created_at >= datetime.now(datetime.UTC) - timedelta(hours=1))
|
||||
.where(SLAViolation.created_at >= datetime.now(timezone.utc) - timedelta(hours=1))
|
||||
)
|
||||
results["violations_detected"] = self.db.execute(stmt).scalar() or 0
|
||||
|
||||
@@ -282,7 +282,7 @@ class SLACollector:
|
||||
) -> List[SLAMetric]:
|
||||
"""Get SLA metrics for a miner or all miners"""
|
||||
|
||||
cutoff = datetime.now(datetime.UTC) - timedelta(hours=hours)
|
||||
cutoff = datetime.now(timezone.utc) - timedelta(hours=hours)
|
||||
|
||||
stmt = select(SLAMetric).where(SLAMetric.timestamp >= cutoff)
|
||||
|
||||
@@ -349,7 +349,7 @@ class SLACollector:
|
||||
metric_value=metric_value,
|
||||
threshold=threshold,
|
||||
violation_duration_ms=None, # Will be updated when resolved
|
||||
created_at=datetime.now(datetime.UTC),
|
||||
created_at=datetime.now(timezone.utc),
|
||||
meta_data=metadata or {},
|
||||
)
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ Tests for Billing Integration Service
|
||||
|
||||
import sys
|
||||
import pytest
|
||||
from datetime import datetime, UTC, timedelta
|
||||
from datetime import datetime, timezone, timedelta
|
||||
from decimal import Decimal
|
||||
from unittest.mock import AsyncMock, patch
|
||||
from sqlalchemy.orm import Session
|
||||
@@ -84,7 +84,7 @@ async def test_record_usage_with_fallback_pricing(billing_integration: BillingIn
|
||||
@pytest.mark.asyncio
|
||||
async def test_sync_miner_usage(billing_integration: BillingIntegration, sample_miner: Miner):
|
||||
"""Test syncing usage for a specific miner"""
|
||||
end_date = datetime.now(datetime.UTC)
|
||||
end_date = datetime.now(timezone.utc)
|
||||
start_date = end_date - timedelta(hours=24)
|
||||
|
||||
with patch("poolhub.services.billing_integration.httpx.AsyncClient") as mock_client:
|
||||
@@ -123,7 +123,7 @@ async def test_sync_all_miners_usage(billing_integration: BillingIntegration, sa
|
||||
|
||||
def test_collect_miner_usage(billing_integration: BillingIntegration, sample_miner: Miner):
|
||||
"""Test collecting usage data for a miner"""
|
||||
end_date = datetime.now(datetime.UTC)
|
||||
end_date = datetime.now(timezone.utc)
|
||||
start_date = end_date - timedelta(hours=24)
|
||||
|
||||
usage_data = billing_integration.db.run_sync(
|
||||
@@ -169,7 +169,7 @@ async def test_trigger_invoice_generation(billing_integration: BillingIntegratio
|
||||
|
||||
mock_client.return_value.__aenter__.return_value.post = AsyncMock(return_value=mock_response)
|
||||
|
||||
end_date = datetime.now(datetime.UTC)
|
||||
end_date = datetime.now(timezone.utc)
|
||||
start_date = end_date - timedelta(days=30)
|
||||
|
||||
result = await billing_integration.trigger_invoice_generation(
|
||||
|
||||
@@ -5,7 +5,7 @@ Tests the integration between pool-hub and coordinator-api's billing system.
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
from datetime import datetime, UTC, timedelta
|
||||
from datetime import datetime, timezone, timedelta
|
||||
from decimal import Decimal
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
@@ -70,7 +70,7 @@ def test_end_to_end_sla_to_billing_workflow(
|
||||
assert len(metrics) > 0
|
||||
|
||||
# Step 3: Collect usage data for billing
|
||||
end_date = datetime.now(datetime.UTC)
|
||||
end_date = datetime.now(timezone.utc)
|
||||
start_date = end_date - timedelta(hours=1)
|
||||
usage_data = sla_collector.db.run_sync(
|
||||
lambda sess: billing_integration._collect_miner_usage(
|
||||
@@ -126,7 +126,7 @@ def test_sla_violation_billing_correlation(
|
||||
assert len(violations) > 0
|
||||
|
||||
# Usage should still be recorded even with violations
|
||||
end_date = datetime.now(datetime.UTC)
|
||||
end_date = datetime.now(timezone.utc)
|
||||
start_date = end_date - timedelta(hours=1)
|
||||
usage_data = sla_collector.db.run_sync(
|
||||
lambda sess: billing_integration._collect_miner_usage(
|
||||
@@ -172,7 +172,7 @@ def test_billing_sync_with_coordinator_api(
|
||||
"""Test billing sync with coordinator-api (mocked)"""
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
end_date = datetime.now(datetime.UTC)
|
||||
end_date = datetime.now(timezone.utc)
|
||||
start_date = end_date - timedelta(hours=1)
|
||||
|
||||
with patch("poolhub.services.billing_integration.httpx.AsyncClient") as mock_client:
|
||||
|
||||
@@ -4,7 +4,7 @@ Tests for SLA Collector Service
|
||||
|
||||
import sys
|
||||
import pytest
|
||||
from datetime import datetime, UTC, timedelta
|
||||
from datetime import datetime, timezone, timedelta
|
||||
from decimal import Decimal
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
@@ -48,7 +48,7 @@ def sample_miner_status(db_session: Session, sample_miner: Miner) -> MinerStatus
|
||||
avg_latency_ms=150,
|
||||
temp_c=65,
|
||||
mem_free_gb=32.0,
|
||||
last_heartbeat_at=datetime.now(datetime.UTC),
|
||||
last_heartbeat_at=datetime.now(timezone.utc),
|
||||
)
|
||||
db_session.add(status)
|
||||
db_session.commit()
|
||||
|
||||
@@ -4,7 +4,7 @@ Tests for SLA API Endpoints
|
||||
|
||||
import sys
|
||||
import pytest
|
||||
from datetime import datetime, UTC, timedelta
|
||||
from datetime import datetime, timezone, timedelta
|
||||
from decimal import Decimal
|
||||
from fastapi.testclient import TestClient
|
||||
from sqlalchemy.orm import Session
|
||||
@@ -65,7 +65,7 @@ def sample_sla_metric(db_session: Session, sample_miner: Miner) -> SLAMetric:
|
||||
metric_value=98.5,
|
||||
threshold=95.0,
|
||||
is_violation=False,
|
||||
timestamp=datetime.now(datetime.UTC),
|
||||
timestamp=datetime.now(timezone.utc),
|
||||
metadata={"test": "true"},
|
||||
)
|
||||
db_session.add(metric)
|
||||
@@ -191,7 +191,7 @@ def test_record_usage(test_client: TestClient):
|
||||
|
||||
def test_generate_invoice(test_client: TestClient):
|
||||
"""Test triggering invoice generation"""
|
||||
end_date = datetime.now(datetime.UTC)
|
||||
end_date = datetime.now(timezone.utc)
|
||||
start_date = end_date - timedelta(days=30)
|
||||
|
||||
request_data = {
|
||||
|
||||
Reference in New Issue
Block a user