Batches never split a postcode 🟥

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-07-07 11:58:41 +00:00
parent bf0d630a8f
commit 80c474b37b
2 changed files with 49 additions and 0 deletions

View file

@ -0,0 +1,19 @@
"""Pack a Modelling Run's resolved properties into SQS-message-sized batches.
Batches stay postcode-grouped properties sharing a postcode ride the same
message so the workers' prediction cohort cache keeps paying (ADR-0055), the
same packing the trigger script has been running.
"""
from backend.app.modelling.property_filters import FilteredProperty
BATCH_SIZE = 50
def pack_postcode_batches(
properties: list[FilteredProperty], batch_size: int = BATCH_SIZE
) -> list[list[FilteredProperty]]:
"""Pack *properties* into batches of ~*batch_size*, never splitting a
postcode across batches. A single postcode larger than *batch_size*
becomes its own oversized batch."""
raise NotImplementedError

View file

@ -0,0 +1,30 @@
from backend.app.modelling.batching import pack_postcode_batches
from backend.app.modelling.property_filters import FilteredProperty
def _properties(postcode: str, count: int, start_id: int) -> list[FilteredProperty]:
return [
FilteredProperty(property_id=start_id + i, postcode=postcode)
for i in range(count)
]
def test_postcodes_are_never_split_across_batches() -> None:
# arrange — 30 + 30 + 10 with a cap of 50: the second postcode won't fit
# alongside the first, the third rides with the second
properties = (
_properties("B93 8SU", 30, start_id=0)
+ _properties("M20 4TF", 30, start_id=100)
+ _properties("SW1A 1AA", 10, start_id=200)
)
# act
batches = pack_postcode_batches(properties, batch_size=50)
# assert
assert [len(b) for b in batches] == [30, 40]
for batch in batches:
for postcode in {p.postcode for p in batch}:
in_batch = [p for p in batch if p.postcode == postcode]
everywhere = [p for p in properties if p.postcode == postcode]
assert len(in_batch) == len(everywhere) # whole postcode, one batch