#!/usr/bin/env python3 """ Test script to verify Snowflake and Feast connectivity. Run this from the feast/ directory with: python test_connection.py """ import os import sys from pathlib import Path def test_snowflake_connection(): """Test 1: Direct Snowflake Connection""" print("=" * 60) print("TEST 1: Direct Snowflake Connection") print("=" * 60) try: import snowflake.connector from cryptography.hazmat.primitives import serialization # Load private key path_str = "/Users/$USER/documents/snowflake_secrets/rsa_key.p8" private_key_path = Path(os.path.expandvars(path_str)) if not private_key_path.exists(): print(f"❌ ERROR: Private key not found at {private_key_path}") return False # Set the environment variable to the private key path os.environ["SNOWFLAKE_PRIVATE_KEY"] = private_key_path.read_text() with open(private_key_path, "rb") as key_file: private_key = serialization.load_pem_private_key( key_file.read(), password=None, # If your key has a passphrase, add it here ) private_key_der = private_key.private_bytes( encoding=serialization.Encoding.DER, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption(), ) print("✅ Private key loaded successfully") # Connect to Snowflake conn = snowflake.connector.connect( account="ccntdmk-suno", user=os.getenv("SNOWFLAKE_USER"), private_key=private_key_der, role="ACCOUNTADMIN", warehouse="DBT_DEV_MEDIUM", database="SUNO_DEV_DELPHINE", schema="PROD", ) print("✅ Connected to Snowflake successfully") # Test query cursor = conn.cursor() cursor.execute("SELECT CURRENT_USER(), CURRENT_ROLE(), CURRENT_WAREHOUSE()") result = cursor.fetchone() print(f" User: {result[0]}") print(f" Role: {result[1]}") print(f" Warehouse: {result[2]}") # Check if table exists cursor.execute(""" SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'PROD' AND TABLE_NAME = 'RECS_HOOKS_RANKER_USER_FEATURE_STORE' """) table_exists = cursor.fetchone()[0] if table_exists: print(f"✅ Table RECS_HOOKS_RANKER_USER_FEATURE_STORE exists") # Get table info cursor.execute(""" SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'PROD' AND TABLE_NAME = 'RECS_HOOKS_RANKER_USER_FEATURE_STORE' ORDER BY ORDINAL_POSITION """) print("\n Table columns:") for col_name, col_type in cursor.fetchall(): print(f" - {col_name}: {col_type}") # Count rows cursor.execute("SELECT COUNT(*) FROM RECS_HOOKS_RANKER_USER_FEATURE_STORE") row_count = cursor.fetchone()[0] print(f"\n Row count: {row_count:,}") # Sample data if row_count > 0: cursor.execute(""" SELECT * FROM RECS_HOOKS_RANKER_USER_FEATURE_STORE LIMIT 3 """) print("\n Sample rows:") for row in cursor.fetchall(): print(f" {row}") else: print(f"❌ Table RECS_HOOKS_RANKER_USER_FEATURE_STORE does not exist") print(" Available tables in PROD schema:") cursor.execute(""" SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'PROD' LIMIT 10 """) for table in cursor.fetchall(): print(f" - {table[0]}") cursor.close() conn.close() print("\n✅ Snowflake connection test PASSED\n") return True except Exception as e: print(f"\n❌ Snowflake connection test FAILED: {e}\n") import traceback traceback.print_exc() return False def test_feast_feature_store(): """Test 2: Feast Feature Store""" print("=" * 60) print("TEST 2: Feast Feature Store") print("=" * 60) try: from feast import FeatureStore # Initialize feature store store = FeatureStore(repo_path=".") print("✅ Feast feature store initialized") # List feature views feature_views = store.list_feature_views() print(f"\n Feature views ({len(feature_views)}):") for fv in feature_views: print(f" - {fv.name}") # List entities entities = store.list_entities() print(f"\n Entities ({len(entities)}):") for entity in entities: print(f" - {entity.name}") print("\n✅ Feast feature store test PASSED\n") return True except Exception as e: print(f"\n❌ Feast feature store test FAILED: {e}\n") print("\nTip: You may need to run 'feast apply' first to register your features.") import traceback traceback.print_exc() return False def test_user_historical_features(): """Test 3: Fetch Historical Features""" print("=" * 60) print("TEST 3: Fetch Historical Features") print("=" * 60) try: import pandas as pd from datetime import datetime, timedelta from feast import FeatureStore store = FeatureStore(repo_path=".") # Create entity dataframe (you'll need real user IDs from your table) entity_df = pd.DataFrame({ "USER_ID": [4937689, 4937689], "event_timestamp": [ datetime.now() - timedelta(days=10), datetime.now(), ], }) print(" Fetching features for users:", entity_df["USER_ID"].tolist()) training_df = store.get_historical_features( entity_df=entity_df, features=["user_features:AVERAGE_WATCH_TIME_30D"], ).to_df() print("\n Retrieved features:") print(training_df) print("\n✅ Historical features fetch test PASSED\n") return True except Exception as e: print(f"\n❌ Historical features fetch test FAILED: {e}\n") import traceback traceback.print_exc() return False def test_user_hook_historical_features(): """Test 4: Fetch User Hook Historical Features""" print("=" * 60) print("TEST 4: Fetch User Hook Historical Features") print("=" * 60) try: import pandas as pd from datetime import datetime from feast import FeatureStore store = FeatureStore(repo_path=".") # Create entity dataframe (you'll need real user IDs from your table) entity_df = pd.DataFrame({ "USER_ID": [4937689], "HOOK_ID": ["7bca153a-0454-4911-ae04-90255821e8e1"], "event_timestamp": [datetime.now()], }) print(" Fetching features for users:", entity_df["USER_ID"].tolist()) training_df = store.get_historical_features( entity_df=entity_df, features=[ "user_hook_features:WATCH_TIME", ], ).to_df() print("\n Retrieved features:") print(training_df) for col in training_df.columns: print(f" - {col}: {training_df[col].iloc[0]}") print("\n✅ User hook historical features fetch test PASSED\n") return True except Exception as e: print(f"\n❌ User hook historical features fetch test FAILED: {e}\n") import traceback traceback.print_exc() return False def test_materialization(): """Test 5: Materialize Features""" print("=" * 60) print("TEST 5: Materialize Features") print("=" * 60) try: from feast import FeatureStore from datetime import datetime, timedelta store = FeatureStore(repo_path=".") end_date = datetime.fromisoformat("2025-09-16T01:00:00") start_date = end_date - timedelta(days=1) print(f"Materializing features from {start_date} to {end_date}") # Materialize to online store (Redis) # in prod, use materialize_incremental instead of materialize store.materialize( start_date=start_date, end_date=end_date, feature_views=["hook_characteristics_features"] ) print("✅ Materialization complete!") return True except Exception as e: print(f"\n❌ Materialization test FAILED: {e}\n") import traceback traceback.print_exc() return False def test_online_features(): """Test 6: Fetch Online Features Note: Assumes features were already materialized in Test 5. If features are None, check that the hook's EVENT_TIMESTAMP matches the materialized date range from Test 5. """ print("=" * 60) print("TEST 6: Fetch Online Features") print("=" * 60) try: from feast import FeatureStore from datetime import datetime import pandas as pd store = FeatureStore(repo_path=".") hook_id = "7bf0047e-7ea9-4fd3-9b86-1c22eef4f14c" # Create entity dataframe (you'll need real user IDs from your table) entity_df = pd.DataFrame({ "HOOK_ID": [hook_id], }) online_df = store.get_online_features( features=["hook_characteristics_features:GEMINI_RATING", "hook_characteristics_features:IS_AI_GENERATED"], entity_rows=entity_df.to_dict(orient="records"), full_feature_names=True, ).to_df() print("\n Retrieved features from Redis:") print(online_df) except Exception as e: print(f"\n❌ Online features fetch test FAILED: {e}\n") import traceback traceback.print_exc() return False print("\n✅ Online features fetch test PASSED\n") return True def main(): """Run all tests""" results = [] # Run tests results.append(("Snowflake Connection", test_snowflake_connection())) results.append(("Feast Feature Store", test_feast_feature_store())) results.append(("Historical Features", test_user_historical_features())) results.append(("User Hook Historical Features", test_user_hook_historical_features())) # Print summary print("=" * 60) print("TEST SUMMARY") print("=" * 60) for test_name, passed in results: status = "✅ PASSED" if passed else "❌ FAILED" print(f"{test_name}: {status}") all_passed = all(passed for _, passed in results) if all_passed: print("\n🎉 ALL TESTS PASSED!") else: print("\n⚠️ Some tests failed. Check the output above for details.") sys.exit(1) if __name__ == "__main__": main()