Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion server.py
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,14 @@ async def get_history(request):
max_items = request.rel_url.query.get("max_items", None)
if max_items is not None:
max_items = int(max_items)
return web.json_response(self.prompt_queue.get_history(max_items=max_items))

offset = request.rel_url.query.get("offset", None)
if offset is not None:
offset = int(offset)
else:
offset = -1

return web.json_response(self.prompt_queue.get_history(max_items=max_items, offset=offset))

@routes.get("/history/{prompt_id}")
async def get_history_prompt_id(request):
Expand Down
105 changes: 104 additions & 1 deletion tests/execution/test_execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,21 @@ def get_history(self, prompt_id):
with urllib.request.urlopen("http://{}/history/{}".format(self.server_address, prompt_id)) as response:
return json.loads(response.read())

def get_all_history(self, max_items=None, offset=None):
url = "http://{}/history".format(self.server_address)
params = {}
if max_items is not None:
params["max_items"] = max_items
if offset is not None:
params["offset"] = offset

if params:
url_values = urllib.parse.urlencode(params)
url = "{}?{}".format(url, url_values)

with urllib.request.urlopen(url) as response:
return json.loads(response.read())

def set_test_name(self, name):
self.test_name = name

Expand Down Expand Up @@ -498,7 +513,6 @@ def test_output_reuse(self, client: ComfyClient, builder: GraphBuilder):
assert len(images1) == 1, "Should have 1 image"
assert len(images2) == 1, "Should have 1 image"


# This tests that only constant outputs are used in the call to `IS_CHANGED`
def test_is_changed_with_outputs(self, client: ComfyClient, builder: GraphBuilder):
g = builder
Expand Down Expand Up @@ -762,3 +776,92 @@ def test_partial_execution_empty_list(self, client: ComfyClient, builder: GraphB
except urllib.error.HTTPError:
pass # Expected behavior

def _create_history_item(self, client, builder):
g = GraphBuilder(prefix="offset_test")
input_node = g.node(
"StubImage", content="BLACK", height=32, width=32, batch_size=1
)
g.node("SaveImage", images=input_node.out(0))
return client.run(g)

def test_offset_returns_different_items_than_beginning_of_history(
self, client: ComfyClient, builder: GraphBuilder
):
"""Test that offset skips items at the beginning"""
for _ in range(5):
self._create_history_item(client, builder)

first_two = client.get_all_history(max_items=2, offset=0)
next_two = client.get_all_history(max_items=2, offset=2)

assert set(first_two.keys()).isdisjoint(
set(next_two.keys())
), "Offset should skip initial items"

def test_offset_beyond_history_length_returns_empty(
self, client: ComfyClient, builder: GraphBuilder
):
"""Test offset larger than total history returns empty result"""
self._create_history_item(client, builder)

result = client.get_all_history(offset=100)
assert len(result) == 0, "Large offset should return no items"

def test_offset_at_exact_history_length_returns_empty(
self, client: ComfyClient, builder: GraphBuilder
):
"""Test offset equal to history length returns empty"""
for _ in range(3):
self._create_history_item(client, builder)

all_history = client.get_all_history()
result = client.get_all_history(offset=len(all_history))
assert len(result) == 0, "Offset at history length should return empty"

def test_offset_zero_equals_no_offset_parameter(
self, client: ComfyClient, builder: GraphBuilder
):
"""Test offset=0 behaves same as omitting offset"""
self._create_history_item(client, builder)

with_zero = client.get_all_history(offset=0)
without_offset = client.get_all_history()

assert with_zero == without_offset, "offset=0 should equal no offset"

def test_offset_without_max_items_skips_from_beginning(
self, client: ComfyClient, builder: GraphBuilder
):
"""Test offset alone (no max_items) returns remaining items"""
for _ in range(4):
self._create_history_item(client, builder)

all_items = client.get_all_history()
offset_items = client.get_all_history(offset=2)

assert (
len(offset_items) == len(all_items) - 2
), "Offset should skip specified number of items"

def test_offset_with_max_items_returns_correct_window(
self, client: ComfyClient, builder: GraphBuilder
):
"""Test offset + max_items returns correct slice of history"""
for _ in range(6):
self._create_history_item(client, builder)

window = client.get_all_history(max_items=2, offset=1)
assert len(window) <= 2, "Should respect max_items limit"

def test_offset_near_end_returns_remaining_items_only(
self, client: ComfyClient, builder: GraphBuilder
):
"""Test offset near end of history returns only remaining items"""
for _ in range(3):
self._create_history_item(client, builder)

all_history = client.get_all_history()
# Offset to near the end
result = client.get_all_history(max_items=5, offset=len(all_history) - 1)

assert len(result) <= 1, "Should return at most 1 item when offset is near end"
Loading