Back-fill hotels/rates counts when marking interrupted scrape batches
cleanup_stale_batches and force_reset_scraper were leaving hotels_found and rates_scraped at 0 because update_scrape_batch never ran — the container was killed before it could. Now we subquery booking_com_rates by scrape_batch_id to show what was actually saved before the interruption. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
9fa4c15081
commit
1acc817999
1 changed files with 34 additions and 8 deletions
|
|
@ -68,11 +68,23 @@ def force_reset_scraper(db: Session) -> dict:
|
||||||
Safe to call even when the lock is not held."""
|
Safe to call even when the lock is not held."""
|
||||||
was_locked = SCRAPE_LOCK.locked()
|
was_locked = SCRAPE_LOCK.locked()
|
||||||
_release_scrape_lock()
|
_release_scrape_lock()
|
||||||
# Mark any batch left in 'running' state as interrupted
|
# Mark any batch left in 'running' state as interrupted, back-filling actual counts
|
||||||
db.execute(text("""
|
db.execute(text("""
|
||||||
UPDATE booking_scrape_log
|
UPDATE booking_scrape_log bsl
|
||||||
SET status = 'interrupted', completed_at = NOW(),
|
SET status = 'interrupted', completed_at = NOW(),
|
||||||
error_message = 'Force-reset by admin'
|
error_message = 'Force-reset by admin',
|
||||||
|
hotels_found = (
|
||||||
|
SELECT COUNT(DISTINCT hotel_id)
|
||||||
|
FROM booking_com_rates
|
||||||
|
WHERE scrape_batch_id = bsl.batch_id::text
|
||||||
|
AND rate_gross IS NOT NULL
|
||||||
|
),
|
||||||
|
rates_scraped = (
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM booking_com_rates
|
||||||
|
WHERE scrape_batch_id = bsl.batch_id::text
|
||||||
|
AND rate_gross IS NOT NULL
|
||||||
|
)
|
||||||
WHERE status = 'running'
|
WHERE status = 'running'
|
||||||
"""))
|
"""))
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
@ -280,16 +292,30 @@ def cleanup_stale_batches(db: Session, max_age_minutes: int = 60):
|
||||||
Mark any 'running' scrape batches as 'failed' if they've been running
|
Mark any 'running' scrape batches as 'failed' if they've been running
|
||||||
longer than max_age_minutes. This handles orphaned batches from
|
longer than max_age_minutes. This handles orphaned batches from
|
||||||
container restarts or crashes.
|
container restarts or crashes.
|
||||||
|
Counts are back-filled from booking_com_rates so the history shows what
|
||||||
|
was actually scraped before the interruption, not zeroes.
|
||||||
"""
|
"""
|
||||||
result = db.execute(
|
result = db.execute(
|
||||||
text("""
|
text("""
|
||||||
UPDATE booking_scrape_log SET
|
UPDATE booking_scrape_log bsl SET
|
||||||
status = 'failed',
|
status = 'failed',
|
||||||
completed_at = NOW(),
|
completed_at = NOW(),
|
||||||
error_message = 'Interrupted (container restart or timeout)'
|
error_message = 'Interrupted (container restart or timeout)',
|
||||||
WHERE status = 'running'
|
hotels_found = (
|
||||||
AND started_at < NOW() - INTERVAL ':mins minutes'
|
SELECT COUNT(DISTINCT hotel_id)
|
||||||
RETURNING batch_id
|
FROM booking_com_rates
|
||||||
|
WHERE scrape_batch_id = bsl.batch_id::text
|
||||||
|
AND rate_gross IS NOT NULL
|
||||||
|
),
|
||||||
|
rates_scraped = (
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM booking_com_rates
|
||||||
|
WHERE scrape_batch_id = bsl.batch_id::text
|
||||||
|
AND rate_gross IS NOT NULL
|
||||||
|
)
|
||||||
|
WHERE bsl.status = 'running'
|
||||||
|
AND bsl.started_at < NOW() - INTERVAL ':mins minutes'
|
||||||
|
RETURNING bsl.batch_id
|
||||||
""".replace(':mins', str(int(max_age_minutes))))
|
""".replace(':mins', str(int(max_age_minutes))))
|
||||||
)
|
)
|
||||||
cleaned = result.fetchall()
|
cleaned = result.fetchall()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue