Skip to content

Commit 4e191f5

Browse files
committed
add checks for data presence in DuckDB tables before replication
1 parent 9bca02c commit 4e191f5

1 file changed

Lines changed: 68 additions & 8 deletions

File tree

src/datasync/pit_registering_salmon.py

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
import os
66
from datetime import datetime, timedelta
7+
from pathlib import Path
78

89
import dlt
10+
import duckdb
911
import requests
1012
import typer
1113
from dlt.sources.helpers.rest_client import RESTClient
@@ -27,6 +29,7 @@
2729
BIOMARK_REGION = env("BIOMARK_REGION", default="us-east-1")
2830
BIOMARK_ACCESS_KEY = env("BIOMARK_ACCESS_KEY", default="")
2931
BIOMARK_SECRET_KEY = env("BIOMARK_SECRET_KEY", default="")
32+
BIOMARK_DUCKDB_PATH = env("BIOMARK_DUCKDB_PATH", default="")
3033

3134
app = typer.Typer()
3235

@@ -299,12 +302,54 @@ def create_stream_config(config: dict, location: str) -> dict:
299302
}
300303

301304

305+
def check_table_has_data(db_path: str, table_name: str) -> bool:
306+
"""
307+
Check if a table exists and has data in the DuckDB database.
308+
309+
Args:
310+
db_path: Path to the DuckDB database file
311+
table_name: Name of the table to check
312+
313+
Returns:
314+
bool: True if table exists and has at least one row, False otherwise
315+
"""
316+
try:
317+
conn = duckdb.connect(db_path, read_only=True)
318+
try:
319+
# check if table exists
320+
result = conn.execute(
321+
"SELECT table_name FROM information_schema.tables WHERE table_name = ?",
322+
[table_name],
323+
).fetchone()
324+
325+
if result is None:
326+
log.info(f"Table {table_name} does not exist")
327+
return False
328+
329+
# check if table has data
330+
count_result = conn.execute(
331+
"SELECT COUNT(*) FROM ?", [table_name]
332+
).fetchone()
333+
row_count = count_result[0] if count_result else 0
334+
335+
log.info(f"Table {table_name} has {row_count} rows")
336+
return row_count > 0
337+
338+
finally:
339+
conn.close()
340+
341+
except Exception as e:
342+
log.error(f"Error checking table {table_name}: {e}")
343+
return False
344+
345+
302346
@app.command()
303347
def replicate(
304348
bucket: str = BIOMARK_BUCKET,
305349
endpoint_url: str = BIOMARK_AWS_ENDPOINT,
306350
access_key: str = BIOMARK_ACCESS_KEY,
307351
secret_key: str = BIOMARK_SECRET_KEY,
352+
duckdb_path: str = BIOMARK_DUCKDB_PATH,
308353
region: str = BIOMARK_REGION,
309354
tags: bool = typer.Option(False, help="Add tags data to S3"),
310355
readers: bool = typer.Option(False, help="Add readers voltage data to S3"),
@@ -316,46 +361,61 @@ def replicate(
316361
os.environ["AWS_SECRET_ACCESS_KEY"] = secret_key
317362
os.environ["AWS_REGION"] = region
318363
os.environ["AWS_ENDPOINT"] = endpoint_url
319-
os.environ["DUCKDB"] = (
320-
"{type: duckdb, instance: biomark_pit_registering_salmon_v1.duckdb}"
321-
)
364+
os.environ["DUCKDB"] = f"{{type: duckdb, instance: {duckdb_path}}}"
322365

323366
if not any([readers, tags, environment]):
324-
typer.echo(
367+
typer.BadParameter(
325368
"Error: At least one data type must be selected "
326369
"(--readers, --tags, or --environment)"
327370
)
328371
raise typer.Exit(1)
329372

330-
# Only include configs for enabled data types
373+
if not Path(duckdb_path).exists():
374+
typer.BadParameter(f"Error: DuckDB file not found at {duckdb_path}")
375+
raise typer.Exit(1)
376+
377+
# only include configs for enabled data types that have data
331378
stream_configs = {}
332379

333-
if readers:
380+
if readers and check_table_has_data(duckdb_path, "readers_voltage"):
334381
stream_configs["readers"] = {
335382
"table_name": "readers_voltage",
336383
"primary_key": ["read_at"],
337384
"update_key": "read_at",
338385
"time_column": "read_at",
339386
"location": "reader__site__slug",
340387
}
388+
log.info("Added readers_voltage to stream config (has data)")
389+
elif readers:
390+
log.warning("--readers_voltage flag is True but table has no data, skipping")
341391

342-
if tags:
392+
if tags and check_table_has_data(duckdb_path, "tags"):
343393
stream_configs["tags"] = {
344394
"table_name": "tags",
345395
"primary_key": ["detected_at"],
346396
"update_key": "detected_at",
347397
"time_column": "detected_at",
348398
"location": "antenna__reader__site__slug",
349399
}
400+
log.info("Added tags to stream config (has data)")
401+
elif tags:
402+
log.warning("--tags flag is set but table has no data, skipping")
350403

351-
if environment:
404+
if environment and check_table_has_data(duckdb_path, "environment_data"):
352405
stream_configs["environment"] = {
353406
"table_name": "environment_data",
354407
"primary_key": ["read_at"],
355408
"update_key": "read_at",
356409
"time_column": "read_at",
357410
"location": "reader__site__slug",
358411
}
412+
log.info("Added environment_data to stream config (has data)")
413+
elif environment:
414+
log.warning("--environment flag is set, but table has no data, skipping")
415+
416+
if not stream_configs:
417+
log.error("No tables with data found to replicate")
418+
raise typer.Exit(1)
359419

360420
streams = {}
361421
for data_type, config in stream_configs.items():

0 commit comments

Comments
 (0)