Skip to content

Commit 25eb7f3

Browse files
committed
fix(experiments): use first-page parent capacity
1 parent 41504be commit 25eb7f3

2 files changed

Lines changed: 50 additions & 1 deletion

File tree

src/jacobian/experiments/service.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -627,11 +627,12 @@ def _run_enumeration(self, experiment_uri: str) -> None:
627627
)
628628
return
629629

630+
fixed_page_parents = 1 if not page_uris else 2
630631
page_size = min(
631632
request.budget.page_size,
632633
remaining_candidates,
633634
self.evaluation.max_batch_size,
634-
self.store.limits.max_parents - 2,
635+
self.store.limits.max_parents - fixed_page_parents,
635636
)
636637
execution = self.executor.run(
637638
entrypoint=enumerator.descriptor.entrypoint,

tests/boundary/storage/recovery/test_enumeration_experiments.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
SearchEnumerateRequest,
1313
)
1414
from jacobian.experiments import ExperimentError, ExperimentNotFoundError
15+
from jacobian.storage.models import StorageLimits
1516

1617

1718
def test_unknown_experiment_error_explains_recovery(
@@ -247,6 +248,53 @@ def test_enumeration_pages_respect_evaluator_batch_limit(
247248
assert snapshot.archive_page_uris[0] in second_page.manifest.parents
248249

249250

251+
def test_enumeration_uses_available_parent_capacity_per_page(
252+
authorized_complete_runtime,
253+
) -> None:
254+
authorized_complete_runtime.core.store.limits = StorageLimits(max_parents=3)
255+
claim_uri, plugin_id = _claim(
256+
authorized_complete_runtime,
257+
reference_name="matrices",
258+
predicate="is_nonsingular",
259+
parameters={},
260+
)
261+
handle = authorized_complete_runtime.services.experiments.start_enumeration(
262+
SearchEnumerateRequest(
263+
claim_uri=claim_uri,
264+
plugin_id=plugin_id,
265+
bounds={"rows": 1, "cols": 1, "entries": [0, 1, 2, 3]},
266+
budget=EnumerationBudget(
267+
candidates_max=4,
268+
wall_seconds=30,
269+
page_size=2,
270+
),
271+
)
272+
)
273+
274+
snapshot = authorized_complete_runtime.services.experiments.wait(
275+
handle.experiment_uri, timeout_seconds=30
276+
)
277+
278+
assert snapshot.state is ExperimentState.COMPLETED
279+
assert snapshot.stop_reason is EnumerationStopReason.COMPLETE
280+
first_page_uri = snapshot.archive_page_uris[0]
281+
first_page = authorized_complete_runtime.core.store.get(first_page_uri)
282+
assert len(first_page.payload["candidate_uris"]) == 2
283+
assert set(first_page.manifest.parents) == {
284+
first_page.payload["evaluation_uris"][0],
285+
*first_page.payload["candidate_uris"],
286+
}
287+
assert len(snapshot.archive_page_uris) == 3
288+
for index, page_uri in enumerate(snapshot.archive_page_uris[1:], start=1):
289+
page = authorized_complete_runtime.core.store.get(page_uri)
290+
assert len(page.payload["candidate_uris"]) == 1
291+
assert set(page.manifest.parents) == {
292+
page.payload["evaluation_uris"][0],
293+
*page.payload["candidate_uris"],
294+
snapshot.archive_page_uris[index - 1],
295+
}
296+
297+
250298
def test_cancellation_never_becomes_an_exhaustive_conclusion(
251299
authorized_complete_runtime,
252300
) -> None:

0 commit comments

Comments
 (0)