Skip to content

Commit e320635

Browse files
add offset param (Comfy-Org#9977)
1 parent 1fee882 commit e320635

File tree

2 files changed

+112
-2
lines changed

2 files changed

+112
-2
lines changed

server.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,14 @@ async def get_history(request):
645645
max_items = request.rel_url.query.get("max_items", None)
646646
if max_items is not None:
647647
max_items = int(max_items)
648-
return web.json_response(self.prompt_queue.get_history(max_items=max_items))
648+
649+
offset = request.rel_url.query.get("offset", None)
650+
if offset is not None:
651+
offset = int(offset)
652+
else:
653+
offset = -1
654+
655+
return web.json_response(self.prompt_queue.get_history(max_items=max_items, offset=offset))
649656

650657
@routes.get("/history/{prompt_id}")
651658
async def get_history_prompt_id(request):

tests/execution/test_execution.py

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,21 @@ def get_history(self, prompt_id):
8484
with urllib.request.urlopen("http://{}/history/{}".format(self.server_address, prompt_id)) as response:
8585
return json.loads(response.read())
8686

87+
def get_all_history(self, max_items=None, offset=None):
88+
url = "http://{}/history".format(self.server_address)
89+
params = {}
90+
if max_items is not None:
91+
params["max_items"] = max_items
92+
if offset is not None:
93+
params["offset"] = offset
94+
95+
if params:
96+
url_values = urllib.parse.urlencode(params)
97+
url = "{}?{}".format(url, url_values)
98+
99+
with urllib.request.urlopen(url) as response:
100+
return json.loads(response.read())
101+
87102
def set_test_name(self, name):
88103
self.test_name = name
89104

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

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

779+
def _create_history_item(self, client, builder):
780+
g = GraphBuilder(prefix="offset_test")
781+
input_node = g.node(
782+
"StubImage", content="BLACK", height=32, width=32, batch_size=1
783+
)
784+
g.node("SaveImage", images=input_node.out(0))
785+
return client.run(g)
786+
787+
def test_offset_returns_different_items_than_beginning_of_history(
788+
self, client: ComfyClient, builder: GraphBuilder
789+
):
790+
"""Test that offset skips items at the beginning"""
791+
for _ in range(5):
792+
self._create_history_item(client, builder)
793+
794+
first_two = client.get_all_history(max_items=2, offset=0)
795+
next_two = client.get_all_history(max_items=2, offset=2)
796+
797+
assert set(first_two.keys()).isdisjoint(
798+
set(next_two.keys())
799+
), "Offset should skip initial items"
800+
801+
def test_offset_beyond_history_length_returns_empty(
802+
self, client: ComfyClient, builder: GraphBuilder
803+
):
804+
"""Test offset larger than total history returns empty result"""
805+
self._create_history_item(client, builder)
806+
807+
result = client.get_all_history(offset=100)
808+
assert len(result) == 0, "Large offset should return no items"
809+
810+
def test_offset_at_exact_history_length_returns_empty(
811+
self, client: ComfyClient, builder: GraphBuilder
812+
):
813+
"""Test offset equal to history length returns empty"""
814+
for _ in range(3):
815+
self._create_history_item(client, builder)
816+
817+
all_history = client.get_all_history()
818+
result = client.get_all_history(offset=len(all_history))
819+
assert len(result) == 0, "Offset at history length should return empty"
820+
821+
def test_offset_zero_equals_no_offset_parameter(
822+
self, client: ComfyClient, builder: GraphBuilder
823+
):
824+
"""Test offset=0 behaves same as omitting offset"""
825+
self._create_history_item(client, builder)
826+
827+
with_zero = client.get_all_history(offset=0)
828+
without_offset = client.get_all_history()
829+
830+
assert with_zero == without_offset, "offset=0 should equal no offset"
831+
832+
def test_offset_without_max_items_skips_from_beginning(
833+
self, client: ComfyClient, builder: GraphBuilder
834+
):
835+
"""Test offset alone (no max_items) returns remaining items"""
836+
for _ in range(4):
837+
self._create_history_item(client, builder)
838+
839+
all_items = client.get_all_history()
840+
offset_items = client.get_all_history(offset=2)
841+
842+
assert (
843+
len(offset_items) == len(all_items) - 2
844+
), "Offset should skip specified number of items"
845+
846+
def test_offset_with_max_items_returns_correct_window(
847+
self, client: ComfyClient, builder: GraphBuilder
848+
):
849+
"""Test offset + max_items returns correct slice of history"""
850+
for _ in range(6):
851+
self._create_history_item(client, builder)
852+
853+
window = client.get_all_history(max_items=2, offset=1)
854+
assert len(window) <= 2, "Should respect max_items limit"
855+
856+
def test_offset_near_end_returns_remaining_items_only(
857+
self, client: ComfyClient, builder: GraphBuilder
858+
):
859+
"""Test offset near end of history returns only remaining items"""
860+
for _ in range(3):
861+
self._create_history_item(client, builder)
862+
863+
all_history = client.get_all_history()
864+
# Offset to near the end
865+
result = client.get_all_history(max_items=5, offset=len(all_history) - 1)
866+
867+
assert len(result) <= 1, "Should return at most 1 item when offset is near end"

0 commit comments

Comments
 (0)