File size: 4,936 Bytes
dc4561e
5d3ee93
dc4561e
 
 
5d3ee93
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dc4561e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5d3ee93
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dc4561e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/bin/bash
# Webapp entrypoint script - restores from S3 and runs database migrations before starting Gunicorn

set -e

echo "[ENTRYPOINT] Checking for S3 restore..."

# Restore database from S3 if enabled (Feature 015)
python3 <<'RESTORE_PYEOF'
import os
import sys

# Add src directory to Python path
sys.path.insert(0, '/app')

try:
    from src.services.s3_restore import restore_on_startup
    
    result = restore_on_startup()
    print(f"[S3_RESTORE] Result: {result.value}")
except Exception as e:
    print(f"[S3_RESTORE] Failed (non-fatal): {e}")
    # Continue startup even if restore fails

RESTORE_PYEOF

echo "[ENTRYPOINT] Running database migrations..."

# Run Python migration script
python3 <<'PYEOF'
import sqlite3
import os

DB_PATH = os.environ.get('DATABASE_PATH', '/app/data/contacts.db')
MIGRATIONS_DIR = '/app/migrations'

print(f"[MIGRATION] Connecting to database: {DB_PATH}")
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()

# Step 1: Check if contact_sessions table exists
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='contact_sessions'")
table_exists = cursor.fetchone() is not None

if not table_exists:
    print("[MIGRATION] Initial database - creating tables from 001_create_tables.sql")
    
    try:
        with open(f'{MIGRATIONS_DIR}/001_create_tables.sql', 'r') as f:
            schema_sql = f.read()
        
        cursor.executescript(schema_sql)
        conn.commit()
        print("  βœ“ Created user_profiles table")
        print("  βœ“ Created contact_sessions table")
        print("  βœ“ Created indexes")
    except Exception as e:
        print(f"  ⚠ Failed to create initial schema: {e}")
        conn.rollback()
        raise

# Step 2: Check if normalized_name column exists (producer columns migration)
cursor.execute("PRAGMA table_info(contact_sessions)")
columns = [row[1] for row in cursor.fetchall()]

# Step 2a: Add contact_id column if missing (v2 API alignment)
if 'contact_id' not in columns:
    print("[MIGRATION] Applying migration: Add contact_id column")
    
    try:
        cursor.execute("ALTER TABLE contact_sessions ADD COLUMN contact_id VARCHAR(255) NOT NULL DEFAULT ''")
        print("  βœ“ Added contact_id column")
    except Exception as e:
        print(f"  ⚠ contact_id: {e}")
    
    try:
        cursor.execute("UPDATE contact_sessions SET contact_id = session_id WHERE contact_id = ''")
        print(f"  βœ“ Backfilled {cursor.rowcount} existing contact_id values")
    except Exception as e:
        print(f"  ⚠ backfill contact_id: {e}")
    
    try:
        cursor.execute("CREATE INDEX IF NOT EXISTS idx_contact_sessions_contact_id ON contact_sessions(contact_id)")
        print("  βœ“ Created index idx_contact_sessions_contact_id")
    except Exception as e:
        print(f"  ⚠ index: {e}")
    
    conn.commit()
    print("[MIGRATION] contact_id migration complete")

# Refresh columns list after contact_id migration
cursor.execute("PRAGMA table_info(contact_sessions)")
columns = [row[1] for row in cursor.fetchall()]

if 'normalized_name' not in columns:
    print("[MIGRATION] Applying migration: Add producer-related columns")
    
    try:
        cursor.execute("ALTER TABLE contact_sessions ADD COLUMN normalized_name TEXT")
        print("  βœ“ Added normalized_name column")
    except Exception as e:
        print(f"  ⚠ normalized_name: {e}")
    
    try:
        cursor.execute("ALTER TABLE contact_sessions ADD COLUMN sequence_number INTEGER DEFAULT 1")
        print("  βœ“ Added sequence_number column")
    except Exception as e:
        print(f"  ⚠ sequence_number: {e}")
    
    try:
        cursor.execute("ALTER TABLE contact_sessions ADD COLUMN producer_id TEXT")
        print("  βœ“ Added producer_id column")
    except Exception as e:
        print(f"  ⚠ producer_id: {e}")
    
    try:
        cursor.execute("CREATE INDEX IF NOT EXISTS idx_contact_sessions_producer ON contact_sessions(user_id, normalized_name)")
        print("  βœ“ Created index idx_contact_sessions_producer")
    except Exception as e:
        print(f"  ⚠ index: {e}")
    
    try:
        cursor.execute("""
            UPDATE contact_sessions
            SET 
                normalized_name = LOWER(TRIM(contact_name)),
                sequence_number = 1,
                producer_id = user_id || '_' || LOWER(TRIM(contact_name)) || '_1'
            WHERE normalized_name IS NULL
        """)
        print(f"  βœ“ Backfilled {cursor.rowcount} existing rows")
    except Exception as e:
        print(f"  ⚠ backfill: {e}")
    
    conn.commit()
    print("[MIGRATION] Migration complete")
else:
    print("[MIGRATION] Schema already up-to-date (normalized_name column exists)")

conn.close()
PYEOF

echo "[ENTRYPOINT] Starting Gunicorn..."

# Start Gunicorn with the provided arguments
exec gunicorn -w 1 -b 0.0.0.0:7860 --timeout 120 --graceful-timeout 120 src.app:app