Send smaller first batch (5 features) for faster first paint
Subsequent batches use the normal batch_size (default 50). This reduces server-side time-to-first-property by ~10x since only 5 features need to be serialized before the first yield.
This commit is contained in:
parent
9179456bf7
commit
e99006e2f9
2 changed files with 40 additions and 4 deletions
31
api/app.py
31
api/app.py
|
|
@ -53,6 +53,7 @@ configure_logging("api")
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
DEFAULT_BATCH_SIZE = 50
|
||||
FIRST_BATCH_SIZE = 5
|
||||
_rate_limit_config = RateLimitConfig.from_env()
|
||||
|
||||
|
||||
|
|
@ -288,6 +289,7 @@ async def _stream_from_cache(
|
|||
}) + "\n"
|
||||
|
||||
count = 0
|
||||
is_first_batch = True
|
||||
for feature_batch in get_cached_features(query_parameters, batch_size=batch_size):
|
||||
# Apply decision filtering
|
||||
if decision_filter != "everything":
|
||||
|
|
@ -302,9 +304,27 @@ async def _stream_from_cache(
|
|||
]
|
||||
if limit and count + len(feature_batch) > limit:
|
||||
feature_batch = feature_batch[:limit - count]
|
||||
count += len(feature_batch)
|
||||
if feature_batch:
|
||||
yield json.dumps({"type": "batch", "features": feature_batch}) + "\n"
|
||||
|
||||
# Split first batch into smaller primer batch and remainder
|
||||
if is_first_batch and len(feature_batch) > FIRST_BATCH_SIZE:
|
||||
# Yield primer batch
|
||||
first_features = feature_batch[:FIRST_BATCH_SIZE]
|
||||
count += len(first_features)
|
||||
yield json.dumps({"type": "batch", "features": first_features}) + "\n"
|
||||
|
||||
# Yield remainder
|
||||
remaining_features = feature_batch[FIRST_BATCH_SIZE:]
|
||||
count += len(remaining_features)
|
||||
if remaining_features:
|
||||
yield json.dumps({"type": "batch", "features": remaining_features}) + "\n"
|
||||
is_first_batch = False
|
||||
else:
|
||||
# Normal batch yielding
|
||||
count += len(feature_batch)
|
||||
if feature_batch:
|
||||
yield json.dumps({"type": "batch", "features": feature_batch}) + "\n"
|
||||
is_first_batch = False
|
||||
|
||||
if limit and count >= limit:
|
||||
break
|
||||
|
||||
|
|
@ -341,6 +361,7 @@ async def _stream_from_db(
|
|||
try:
|
||||
count = 0
|
||||
batch: list[dict] = []
|
||||
current_batch_target = FIRST_BATCH_SIZE # Start with smaller first batch
|
||||
for row in repository.stream_listings_optimized(
|
||||
query_parameters, limit=limit, page_size=batch_size
|
||||
):
|
||||
|
|
@ -359,11 +380,13 @@ async def _stream_from_db(
|
|||
batch.append(feature)
|
||||
count += 1
|
||||
|
||||
if len(batch) >= batch_size:
|
||||
if len(batch) >= current_batch_target:
|
||||
if staging_key:
|
||||
cache_features_batch_staged(staging_key, batch)
|
||||
yield json.dumps({"type": "batch", "features": batch}) + "\n"
|
||||
batch = []
|
||||
# After first batch, use normal batch size
|
||||
current_batch_target = batch_size
|
||||
|
||||
if batch:
|
||||
if staging_key:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue