Skip to content

Commit cfd8505

Browse files
committed
updates from reviews
1 parent 0f011c3 commit cfd8505

File tree

2 files changed

+14
-48
lines changed

2 files changed

+14
-48
lines changed

src/guidellm/scheduler/objects.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111

1212
import time
1313
import uuid
14-
from abc import ABC, abstractmethod
1514
from collections.abc import AsyncIterator
1615
from typing import (
1716
Any,
1817
Generic,
1918
Literal,
19+
Protocol,
2020
TypeVar,
2121
Union,
2222
)
@@ -59,7 +59,10 @@
5959

6060

6161
class RequestSchedulerTimings(StandardBaseModel):
62-
"""Scheduler-level timing measurements for request lifecycle tracking."""
62+
"""
63+
Scheduler-level timing measurements for request lifecycle tracking.
64+
All timestamps are expected to be in Unix time (seconds since epoch).
65+
"""
6366

6467
targeted_start: float | None = Field(
6568
default=None,
@@ -89,7 +92,10 @@ class RequestSchedulerTimings(StandardBaseModel):
8992

9093

9194
class MeasuredRequestTimings(StandardBaseModel):
92-
"""Base timing measurements for backend request processing."""
95+
"""
96+
Base timing measurements for backend request processing.
97+
All timestamps are expected to be in Unix time (seconds since epoch).
98+
"""
9399

94100
request_start: float | None = Field(
95101
default=None, description="When the backend began processing the request"
@@ -203,7 +209,7 @@ def model_copy(self, **kwargs) -> ScheduledRequestInfo: # type: ignore[override
203209
)
204210

205211

206-
class BackendInterface(ABC, Generic[RequestT, MeasuredRequestTimingsT, ResponseT]):
212+
class BackendInterface(Protocol, Generic[RequestT, MeasuredRequestTimingsT, ResponseT]):
207213
"""
208214
Abstract interface for request processing backends.
209215
@@ -227,52 +233,44 @@ async def resolve(self, request, request_info, history=None):
227233
"""
228234

229235
@property
230-
@abstractmethod
231236
def processes_limit(self) -> int | None:
232237
"""
233238
:return: Maximum worker processes supported, or None if unlimited
234239
"""
235240

236241
@property
237-
@abstractmethod
238242
def requests_limit(self) -> int | None:
239243
"""
240244
:return: Maximum concurrent requests supported, or None if unlimited
241245
"""
242246

243247
@property
244-
@abstractmethod
245248
def info(self) -> dict[str, Any]:
246249
"""
247250
:return: Backend metadata including model initialization and configuration
248251
"""
249-
...
250252

251-
@abstractmethod
252253
async def process_startup(self) -> None:
253254
"""
254255
Perform backend initialization and startup procedures.
255256
256257
:raises: Implementation-specific exceptions for startup failures.
257258
"""
258259

259-
@abstractmethod
260260
async def validate(self) -> None:
261261
"""
262262
Validate backend configuration and operational status.
263263
264264
:raises: Implementation-specific exceptions for validation failures.
265265
"""
266266

267-
@abstractmethod
268267
async def process_shutdown(self) -> None:
269268
"""
270269
Perform backend cleanup and shutdown procedures.
271270
272271
:raises: Implementation-specific exceptions for shutdown failures.
273272
"""
274273

275-
@abstractmethod
276274
async def resolve(
277275
self,
278276
request: RequestT,

tests/unit/scheduler/test_objects.py

Lines changed: 4 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import inspect
44
import typing
5-
from abc import ABC
65
from collections.abc import AsyncIterator
76
from typing import Any, Optional, TypeVar, Union
87

@@ -76,13 +75,6 @@ def test_multi_turn_request_t():
7675
class TestBackendInterface:
7776
"""Test the BackendInterface abstract base class."""
7877

79-
@pytest.mark.smoke
80-
def test_is_abstract_base_class(self):
81-
"""Test that BackendInterface is an ABC and cannot be instantiated directly."""
82-
assert issubclass(BackendInterface, ABC)
83-
with pytest.raises(TypeError, match="Can't instantiate abstract class"):
84-
BackendInterface()
85-
8678
@pytest.mark.smoke
8779
def test_abstract_methods_defined(self):
8880
"""Test that all expected abstract methods are defined."""
@@ -112,17 +104,17 @@ def test_abstract_methods_defined(self):
112104
def test_generic_type_parameters(self):
113105
"""Test that BackendInterface has the correct generic type parameters."""
114106
orig_bases = BackendInterface.__orig_bases__
115-
abc_base = None
107+
protocol_base = None
116108
generic_base = None
117109

118110
for base in orig_bases:
119111
if hasattr(base, "__origin__"):
120112
if base.__origin__ is typing.Generic:
121113
generic_base = base
122-
elif base.__name__ == "ABC":
123-
abc_base = base
114+
elif base.__name__ == "Protocol":
115+
protocol_base = base
124116

125-
assert abc_base is not None, "Should inherit from ABC"
117+
assert protocol_base is not None, "Should inherit from Protocol"
126118
assert generic_base is not None, "Should inherit from Generic"
127119

128120
if hasattr(generic_base, "__args__"):
@@ -132,30 +124,6 @@ def test_generic_type_parameters(self):
132124
expected_names = ["RequestT", "MeasuredRequestTimingsT", "ResponseT"]
133125
assert param_names == expected_names
134126

135-
@pytest.mark.sanity
136-
def test_invalid_implementation(self):
137-
"""Test that a concrete implementation must implement all abstract methods."""
138-
139-
class PartialBackend(BackendInterface):
140-
@property
141-
def processes_limit(self):
142-
return 1
143-
144-
@property
145-
def requests_limit(self):
146-
return 10
147-
148-
def info(self):
149-
return {}
150-
151-
async def process_startup(self):
152-
pass
153-
154-
# Missing: validate, process_shutdown, resolve
155-
156-
with pytest.raises(TypeError, match="Can't instantiate abstract class"):
157-
PartialBackend()
158-
159127
@pytest.mark.smoke
160128
def test_implementation_construction(self):
161129
"""Test that a complete concrete implementation can be instantiated."""

0 commit comments

Comments
 (0)