···11-# SQLx Offline and Cross-Compilation Setup
22-33-This document explains the configuration changes made to support SQLx offline builds and fix cross-compilation issues.
44-55-## Problems Solved
66-77-### 1. SQLx Offline Compilation
88-When `SQLX_OFFLINE=true`, each Rust project needs access to `.sqlx` query metadata files in their local directory. Previously, these files only existed at the workspace root, causing builds to fail outside Docker.
99-1010-### 2. Cross-Compilation OpenSSL Issues
1111-Cross-compilation was failing due to OpenSSL dependencies being pulled in by various crates, which is notoriously difficult to cross-compile.
1212-1313-## Solutions Implemented
1414-1515-### SQLx Offline Setup
1616-1717-#### Script: `scripts/setup-sqlx-offline.sh`
1818-- Automatically copies `.sqlx` files from workspace root to each SQLx-dependent project
1919-- Identifies projects that use SQLx by checking `Cargo.toml` files
2020-- Projects that receive `.sqlx` files:
2121- - `apps/aqua`
2222- - `services/cadet`
2323- - `services/satellite`
2424-2525-#### CI Integration
2626-The script is now called in all CI jobs that build Rust code:
2727-- `setup-and-build` job
2828-- `rust-cross-compile` job
2929-- `rust-quality` job
3030-- `security-audit` job
3131-3232-### Cross-Compilation Fixes
3333-3434-#### 1. Replaced OpenSSL with rustls
3535-Updated workspace dependencies to use rustls instead of OpenSSL:
3636-3737-```toml
3838-# Root Cargo.toml
3939-tokio = { version = "1.0", features = [
4040- "rt-multi-thread",
4141- "macros",
4242- "time", # Required for tokio::time module
4343- "net", # Required for networking
4444- "sync", # Required for synchronization primitives
4545-] }
4646-4747-sqlx = { version = "0.8", features = [
4848- "runtime-tokio",
4949- "postgres",
5050- "uuid",
5151- "tls-rustls", # Instead of default OpenSSL
5252-] }
5353-5454-reqwest = { version = "0.12", default-features = false, features = [
5555- "json",
5656- "rustls-tls", # Instead of default native-tls
5757- "stream",
5858- "gzip",
5959-] }
6060-6161-tokio-tungstenite = { version = "*", default-features = false, features = [
6262- "rustls-tls-webpki-roots", # Instead of default native-tls
6363- "connect", # For connect_async function
6464- "handshake", # For accept_async function (tests)
6565-] }
6666-```
6767-6868-#### 2. Fixed Workspace Dependency Conflicts
6969-The `services/Cargo.toml` was overriding workspace dependencies with different configurations. Fixed by:
7070-- Changing `reqwest = { version = "0.12", features = ["json"] }` to `reqwest.workspace = true`
7171-- Changing `tokio-tungstenite = "0.24"` to `tokio-tungstenite.workspace = true`
7272-7373-#### 3. Enhanced Cross.toml Configuration
7474-Created comprehensive `Cross.toml` files for cross-compilation:
7575-7676-```toml
7777-[build.env]
7878-passthrough = [
7979- "CARGO_HOME",
8080- "CARGO_TARGET_DIR",
8181- "SQLX_OFFLINE",
8282- "PKG_CONFIG_ALLOW_CROSS",
8383-]
8484-8585-[target.aarch64-unknown-linux-gnu]
8686-image = "ghcr.io/cross-rs/aarch64-unknown-linux-gnu:main"
8787-8888-[target.aarch64-unknown-linux-gnu.env]
8989-passthrough = ["CARGO_HOME", "CARGO_TARGET_DIR", "SQLX_OFFLINE"]
9090-PKG_CONFIG_ALLOW_CROSS = "1"
9191-RUSTFLAGS = "-C target-feature=+crt-static -C link-arg=-s"
9292-CC_aarch64_unknown_linux_gnu = "aarch64-linux-gnu-gcc"
9393-CXX_aarch64_unknown_linux_gnu = "aarch64-linux-gnu-g++"
9494-```
9595-9696-#### 4. Improved CI Cross-Compilation
9797-- Uses latest `cross` from Git: `cargo install cross --git https://github.com/cross-rs/cross`
9898-- Sets `PKG_CONFIG_ALLOW_CROSS=1` environment variable
9999-- Copies `.sqlx` files to individual service directories during cross-compilation
100100-- Improved executable collection with better filtering
101101-102102-### Executable Collection
103103-104104-Enhanced executable collection in CI:
105105-- Filters out build artifacts (`.d` files and temporary files with `-` in names)
106106-- Handles missing target directories gracefully
107107-- Collects executables for both x86_64 and aarch64 targets
108108-- Provides clear logging of collected executables
109109-110110-## File Changes
111111-112112-### Created
113113-- `scripts/setup-sqlx-offline.sh` - SQLx offline setup script
114114-- `Cross.toml` - Root cross-compilation config
115115-- `services/Cross.toml` - Services cross-compilation config
116116-- `apps/aqua/Cross.toml` - Aqua cross-compilation config
117117-118118-### Modified
119119-- `Cargo.toml` - Updated workspace dependencies to use rustls
120120-- `services/Cargo.toml` - Fixed workspace dependency usage
121121-- `.github/workflows/ci.yml` - Added SQLx setup and improved cross-compilation
122122-123123-## Usage
124124-125125-### Running SQLx Setup Locally
126126-```bash
127127-./scripts/setup-sqlx-offline.sh
128128-```
129129-130130-### Cross-Compilation Locally
131131-```bash
132132-# Install cross if not already installed
133133-cargo install cross --git https://github.com/cross-rs/cross
134134-135135-# Add target
136136-rustup target add aarch64-unknown-linux-gnu
137137-138138-# Set environment
139139-export PKG_CONFIG_ALLOW_CROSS=1
140140-export SQLX_OFFLINE=true
141141-142142-# Run SQLx setup
143143-./scripts/setup-sqlx-offline.sh
144144-145145-# Cross-compile services
146146-cd services
147147-cross build --release --target aarch64-unknown-linux-gnu
148148-149149-# Cross-compile apps
150150-cd ../apps/aqua
151151-cross build --release --target aarch64-unknown-linux-gnu
152152-```
153153-154154-### Updating SQLx Queries
155155-When you add or modify SQL queries:
156156-157157-1. Generate new query metadata from the services directory:
158158- ```bash
159159- cd services
160160- cargo sqlx prepare
161161- ```
162162-163163-2. Update all project copies:
164164- ```bash
165165- ./scripts/setup-sqlx-offline.sh
166166- ```
167167-168168-## Troubleshooting
169169-170170-### Cross-Compilation Still Fails
171171-- Ensure you're using the latest `cross` from Git
172172-- Check that `PKG_CONFIG_ALLOW_CROSS=1` is set
173173-- Verify no dependencies are pulling in OpenSSL (use `cargo tree | grep openssl`)
174174-175175-### tokio-tungstenite Import Errors
176176-If you see "unresolved import `tokio_tungstenite::connect_async`" errors:
177177-- Ensure the `connect` feature is enabled for client functionality
178178-- Add the `handshake` feature if using `accept_async` for server functionality
179179-- Check that `default-features = false` is set to avoid OpenSSL dependencies
180180-181181-### tokio Module Errors
182182-If you see "could not find `time` in `tokio`" or similar errors:
183183-- Ensure tokio workspace dependency includes required features: `time`, `net`, `sync`
184184-- These features are often included in default features but must be explicit when using `default-features = false`
185185-186186-### SQLx Offline Errors
187187-- Run `./scripts/setup-sqlx-offline.sh` after any SQL query changes
188188-- Ensure `.sqlx` directory exists in workspace root
189189-- Check that `SQLX_OFFLINE=true` is set in CI environment
190190-191191-### Missing Executables
192192-- Check that build succeeded without errors
193193-- Verify executable names match expected service/app names
194194-- Look for executables in `artifacts/` directory structure
195195-196196-## Dependencies Avoided
197197-To maintain cross-compilation compatibility, avoid dependencies that:
198198-- Default to OpenSSL (use rustls variants)
199199-- Require system libraries not available in cross containers
200200-- Have complex native build requirements
201201-202202-### Common Feature Configuration Issues
203203-When disabling default features to avoid OpenSSL:
204204-- `tokio`: Must explicitly enable `time`, `net`, `sync` features for common functionality
205205-- `tokio-tungstenite`: Must explicitly enable `connect` and `handshake` features
206206-- `reqwest`: Must explicitly enable required features like `json`, `stream`, `gzip`
207207-- `sqlx`: Use `tls-rustls` instead of default OpenSSL TLS
208208-209209-Always test cross-compilation locally before pushing changes.
-355
docs/migration-troubleshooting.md
···11-# Migration Troubleshooting Guide
22-33-## Common Migration Issues and Solutions
44-55-### Issue: "cannot drop function because other objects depend on it"
66-77-**Error Message:**
88-```
99-error: while executing migration 20241220000008: error returned from database: cannot drop function extract_discriminant(text) because other objects depend on it
1010-```
1111-1212-**Cause:**
1313-This error occurs when trying to drop database functions that have dependent objects (views, other functions, triggers, etc.) without properly handling the dependencies.
1414-1515-**Solution:**
1616-1717-#### Option 1: Fix the Migration (Recommended)
1818-Update the problematic migration to handle dependencies properly:
1919-2020-1. **Edit the migration file** (e.g., `20241220000008_fix_discriminant_case_sensitivity.sql`):
2121-2222-```sql
2323--- Drop dependent views first, then functions, then recreate everything
2424-DROP VIEW IF EXISTS discriminant_analysis CASCADE;
2525-DROP VIEW IF EXISTS discriminant_stats CASCADE;
2626-2727--- Drop existing functions with CASCADE to handle dependencies
2828-DROP FUNCTION IF EXISTS extract_discriminant(TEXT) CASCADE;
2929-DROP FUNCTION IF EXISTS get_base_name(TEXT) CASCADE;
3030-DROP FUNCTION IF EXISTS extract_edition_discriminant(TEXT) CASCADE;
3131-3232--- Then recreate functions and views...
3333-```
3434-3535-2. **Reset the migration state** if the migration was partially applied:
3636-3737-```bash
3838-# Connect to your database and reset the specific migration
3939-psql $DATABASE_URL -c "DELETE FROM _sqlx_migrations WHERE version = '20241220000008';"
4040-4141-# Or reset all migrations and start fresh (WARNING: This drops all data)
4242-psql $DATABASE_URL -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"
4343-```
4444-4545-3. **Run migrations again**:
4646-```bash
4747-cd services
4848-DATABASE_URL="your_database_url" sqlx migrate run
4949-```
5050-5151-#### Option 2: Manual Dependency Cleanup
5252-If you can't modify the migration file:
5353-5454-1. **Identify dependencies**:
5555-```sql
5656--- Find objects that depend on the function
5757-SELECT
5858- p.proname as function_name,
5959- d.objid,
6060- d.classid::regclass as object_type,
6161- d.refobjid
6262-FROM pg_depend d
6363-JOIN pg_proc p ON d.refobjid = p.oid
6464-WHERE p.proname = 'extract_discriminant';
6565-```
6666-6767-2. **Drop dependencies manually**:
6868-```sql
6969--- Drop dependent views
7070-DROP VIEW IF EXISTS discriminant_analysis CASCADE;
7171-DROP VIEW IF EXISTS discriminant_stats CASCADE;
7272-DROP VIEW IF EXISTS track_variants CASCADE;
7373-DROP VIEW IF EXISTS release_variants CASCADE;
7474-7575--- Drop the functions
7676-DROP FUNCTION IF EXISTS extract_discriminant(TEXT) CASCADE;
7777-DROP FUNCTION IF EXISTS get_base_name(TEXT) CASCADE;
7878-DROP FUNCTION IF EXISTS extract_edition_discriminant(TEXT) CASCADE;
7979-```
8080-8181-3. **Continue with migration**:
8282-```bash
8383-DATABASE_URL="your_database_url" sqlx migrate run
8484-```
8585-8686-### Issue: "migration was previously applied but has been modified"
8787-8888-**Error Message:**
8989-```
9090-error: migration 20241220000008 was previously applied but has been modified
9191-```
9292-9393-**Cause:**
9494-The migration file has been changed after it was already applied to the database.
9595-9696-**Solutions:**
9797-9898-#### Option 1: Reset Migration State
9999-```bash
100100-# Remove the specific migration from tracking
101101-psql $DATABASE_URL -c "DELETE FROM _sqlx_migrations WHERE version = '20241220000008';"
102102-103103-# Run migrations again
104104-DATABASE_URL="your_database_url" sqlx migrate run
105105-```
106106-107107-#### Option 2: Create a New Migration
108108-```bash
109109-# Create a new migration with your changes
110110-sqlx migrate add fix_discriminant_case_sensitivity_v2
111111-112112-# Copy your changes to the new migration file
113113-# Run the new migration
114114-DATABASE_URL="your_database_url" sqlx migrate run
115115-```
116116-117117-#### Option 3: Full Reset (WARNING: Destroys all data)
118118-```bash
119119-# Connect to database and reset everything
120120-psql $DATABASE_URL -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"
121121-122122-# Run all migrations from scratch
123123-DATABASE_URL="your_database_url" sqlx migrate run
124124-```
125125-126126-### Issue: "No such file or directory" when running migrations
127127-128128-**Error Message:**
129129-```
130130-error: while resolving migrations: No such file or directory (os error 2)
131131-```
132132-133133-**Cause:**
134134-The migration directory is not found in the expected location.
135135-136136-**Solutions:**
137137-138138-#### Option 1: Check Migration Directory Location
139139-```bash
140140-# Check where sqlx expects migrations
141141-cat services/.sqlx/.sqlxrc
142142-143143-# Ensure migrations exist in the correct location
144144-ls -la services/migrations/
145145-```
146146-147147-#### Option 2: Copy Migrations to Correct Location
148148-```bash
149149-# If migrations are in wrong location, copy them
150150-cp migrations/*.sql services/migrations/
151151-152152-# Or create symlink
153153-ln -s ../migrations services/migrations
154154-```
155155-156156-#### Option 3: Update sqlx Configuration
157157-Edit `services/.sqlx/.sqlxrc`:
158158-```toml
159159-[database]
160160-url = "postgres://localhost/teal"
161161-migrations = "../migrations" # Update path as needed
162162-```
163163-164164-### Issue: Database Connection Problems
165165-166166-**Error Messages:**
167167-- `Connection refused (os error 61)`
168168-- `password authentication failed`
169169-- `database "teal_test" does not exist`
170170-171171-**Solutions:**
172172-173173-#### Connection Refused
174174-```bash
175175-# Check if database is running
176176-docker ps | grep postgres
177177-178178-# Start database if needed
179179-docker-compose -f compose.db-test.yml up -d
180180-181181-# Wait for database to start
182182-sleep 5
183183-```
184184-185185-#### Authentication Issues
186186-```bash
187187-# Check connection string format
188188-DATABASE_URL="postgres://username:password@host:port/database"
189189-190190-# Example for test database
191191-DATABASE_URL="postgres://postgres:testpass123@localhost:5433/teal_test"
192192-```
193193-194194-#### Database Doesn't Exist
195195-```bash
196196-# Create database
197197-docker exec postgres_container psql -U postgres -c "CREATE DATABASE teal_test;"
198198-199199-# Or recreate test environment
200200-docker-compose -f compose.db-test.yml down
201201-docker-compose -f compose.db-test.yml up -d
202202-```
203203-204204-## Migration Best Practices
205205-206206-### 1. Handle Dependencies Properly
207207-Always use `CASCADE` when dropping objects with dependencies:
208208-```sql
209209-DROP FUNCTION function_name(args) CASCADE;
210210-DROP VIEW view_name CASCADE;
211211-```
212212-213213-### 2. Test Migrations Locally
214214-```bash
215215-# Use test database for migration testing
216216-DATABASE_URL="postgres://localhost:5433/teal_test" sqlx migrate run
217217-218218-# Verify results
219219-psql "postgres://localhost:5433/teal_test" -c "SELECT extract_discriminant('Test (Example)');"
220220-```
221221-222222-### 3. Backup Before Major Migrations
223223-```bash
224224-# Create backup
225225-pg_dump $DATABASE_URL > backup_before_migration.sql
226226-227227-# Apply migrations
228228-sqlx migrate run
229229-230230-# Restore if needed
231231-psql $DATABASE_URL < backup_before_migration.sql
232232-```
233233-234234-### 4. Version Control Migration Files
235235-- Never modify applied migrations
236236-- Create new migrations for changes
237237-- Use descriptive migration names
238238-- Include rollback instructions in comments
239239-240240-### 5. Migration File Structure
241241-```sql
242242--- Migration: descriptive_name
243243--- Purpose: Brief description of what this migration does
244244--- Dependencies: List any required prior migrations
245245--- Rollback: Instructions for manual rollback if needed
246246-247247--- Drop dependencies first
248248-DROP VIEW IF EXISTS dependent_view CASCADE;
249249-250250--- Make changes
251251-CREATE OR REPLACE FUNCTION new_function() ...;
252252-253253--- Recreate dependencies
254254-CREATE VIEW dependent_view AS ...;
255255-256256--- Update existing data if needed
257257-UPDATE table_name SET column = new_value WHERE condition;
258258-259259--- Add comments
260260-COMMENT ON FUNCTION new_function IS 'Description of function purpose';
261261-```
262262-263263-## Emergency Recovery
264264-265265-### Complete Database Reset
266266-If migrations are completely broken:
267267-268268-```bash
269269-# 1. Stop all services
270270-docker-compose down
271271-272272-# 2. Remove database volume (WARNING: Destroys all data)
273273-docker volume rm teal_postgres_data
274274-275275-# 3. Start fresh
276276-docker-compose up -d postgres
277277-278278-# 4. Wait for database to initialize
279279-sleep 10
280280-281281-# 5. Run all migrations from scratch
282282-DATABASE_URL="your_database_url" sqlx migrate run
283283-```
284284-285285-### Partial Recovery
286286-If only discriminant system is broken:
287287-288288-```sql
289289--- Remove discriminant-related objects
290290-DROP VIEW IF EXISTS discriminant_analysis CASCADE;
291291-DROP VIEW IF EXISTS discriminant_stats CASCADE;
292292-DROP VIEW IF EXISTS track_variants CASCADE;
293293-DROP VIEW IF EXISTS release_variants CASCADE;
294294-DROP FUNCTION IF EXISTS extract_discriminant(TEXT) CASCADE;
295295-DROP FUNCTION IF EXISTS get_base_name(TEXT) CASCADE;
296296-DROP FUNCTION IF EXISTS extract_edition_discriminant(TEXT) CASCADE;
297297-298298--- Remove discriminant columns
299299-ALTER TABLE plays DROP COLUMN IF EXISTS track_discriminant;
300300-ALTER TABLE plays DROP COLUMN IF EXISTS release_discriminant;
301301-ALTER TABLE recordings DROP COLUMN IF EXISTS discriminant;
302302-ALTER TABLE releases DROP COLUMN IF EXISTS discriminant;
303303-304304--- Mark discriminant migrations as not applied
305305-DELETE FROM _sqlx_migrations WHERE version >= '20241220000006';
306306-307307--- Re-run discriminant migrations
308308-```
309309-310310-## Getting Help
311311-312312-### Debug Information to Collect
313313-When reporting migration issues, include:
314314-315315-1. **Error message** (full stack trace)
316316-2. **Migration file content** that's causing issues
317317-3. **Database state**:
318318- ```sql
319319- SELECT version FROM _sqlx_migrations ORDER BY version;
320320- \df extract_discriminant
321321- \dv discriminant_*
322322- ```
323323-4. **Environment details**:
324324- - Database version: `SELECT version();`
325325- - Operating system
326326- - sqlx version: `cargo sqlx --version`
327327-328328-### Useful Debugging Commands
329329-```sql
330330--- Check applied migrations
331331-SELECT * FROM _sqlx_migrations ORDER BY version;
332332-333333--- Check function definitions
334334-\df+ extract_discriminant
335335-336336--- Check view definitions
337337-\d+ discriminant_analysis
338338-339339--- Check table schemas
340340-\d+ plays
341341-\d+ recordings
342342-\d+ releases
343343-344344--- Test function directly
345345-SELECT extract_discriminant('Test (Example)');
346346-```
347347-348348-## Contact and Support
349349-350350-For persistent migration issues:
351351-1. Check this troubleshooting guide first
352352-2. Review the specific migration file causing issues
353353-3. Try solutions in order of preference (fix migration → manual cleanup → reset)
354354-4. Create minimal reproduction case for complex issues
355355-5. Document exact steps that led to the error for support requests