Initial commit: VMware vSphere API simulator scaffold.
Add the FastAPI app, PostgreSQL migrations, Docker/Helm packaging, API contracts, docs, client examples, and the unit/integration/compatibility test suite for local client and tooling labs without a real vCenter.
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
"""Injectable simulation clocks; task leases deliberately do not use these."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from datetime import UTC, datetime, timedelta
|
||||
from typing import Protocol
|
||||
|
||||
|
||||
class Clock(Protocol):
|
||||
async def now(self) -> datetime: ...
|
||||
|
||||
async def sleep(self, seconds: float) -> None: ...
|
||||
|
||||
|
||||
class RealClock:
|
||||
async def now(self) -> datetime:
|
||||
return datetime.now(UTC)
|
||||
|
||||
async def sleep(self, seconds: float) -> None:
|
||||
await asyncio.sleep(seconds)
|
||||
|
||||
|
||||
class AcceleratedClock:
|
||||
def __init__(self, scale: float) -> None:
|
||||
if scale <= 0:
|
||||
raise ValueError("clock scale must be positive")
|
||||
self._scale = scale
|
||||
|
||||
async def now(self) -> datetime:
|
||||
return datetime.now(UTC)
|
||||
|
||||
async def sleep(self, seconds: float) -> None:
|
||||
await asyncio.sleep(seconds / self._scale)
|
||||
|
||||
|
||||
class ManualClock:
|
||||
def __init__(self, initial: datetime) -> None:
|
||||
if initial.tzinfo is None:
|
||||
raise ValueError("manual clock requires timezone-aware time")
|
||||
self._now = initial
|
||||
self._condition = asyncio.Condition()
|
||||
|
||||
async def now(self) -> datetime:
|
||||
async with self._condition:
|
||||
return self._now
|
||||
|
||||
async def sleep(self, seconds: float) -> None:
|
||||
if seconds < 0:
|
||||
raise ValueError("sleep duration cannot be negative")
|
||||
async with self._condition:
|
||||
target = self._now + timedelta(seconds=seconds)
|
||||
await self._condition.wait_for(lambda: self._now >= target)
|
||||
|
||||
async def advance(self, seconds: float) -> datetime:
|
||||
if seconds < 0:
|
||||
raise ValueError("clock cannot move backwards")
|
||||
async with self._condition:
|
||||
self._now += timedelta(seconds=seconds)
|
||||
self._condition.notify_all()
|
||||
return self._now
|
||||
Reference in New Issue
Block a user