-209
.github/SQLX_AND_CROSS_COMPILATION.md
-209
.github/SQLX_AND_CROSS_COMPILATION.md
···
1
-
# SQLx Offline and Cross-Compilation Setup
2
-
3
-
This document explains the configuration changes made to support SQLx offline builds and fix cross-compilation issues.
4
-
5
-
## Problems Solved
6
-
7
-
### 1. SQLx Offline Compilation
8
-
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.
9
-
10
-
### 2. Cross-Compilation OpenSSL Issues
11
-
Cross-compilation was failing due to OpenSSL dependencies being pulled in by various crates, which is notoriously difficult to cross-compile.
12
-
13
-
## Solutions Implemented
14
-
15
-
### SQLx Offline Setup
16
-
17
-
#### Script: `scripts/setup-sqlx-offline.sh`
18
-
- Automatically copies `.sqlx` files from workspace root to each SQLx-dependent project
19
-
- Identifies projects that use SQLx by checking `Cargo.toml` files
20
-
- Projects that receive `.sqlx` files:
21
-
- `apps/aqua`
22
-
- `services/cadet`
23
-
- `services/satellite`
24
-
25
-
#### CI Integration
26
-
The script is now called in all CI jobs that build Rust code:
27
-
- `setup-and-build` job
28
-
- `rust-cross-compile` job
29
-
- `rust-quality` job
30
-
- `security-audit` job
31
-
32
-
### Cross-Compilation Fixes
33
-
34
-
#### 1. Replaced OpenSSL with rustls
35
-
Updated workspace dependencies to use rustls instead of OpenSSL:
36
-
37
-
```toml
38
-
# Root Cargo.toml
39
-
tokio = { version = "1.0", features = [
40
-
"rt-multi-thread",
41
-
"macros",
42
-
"time", # Required for tokio::time module
43
-
"net", # Required for networking
44
-
"sync", # Required for synchronization primitives
45
-
] }
46
-
47
-
sqlx = { version = "0.8", features = [
48
-
"runtime-tokio",
49
-
"postgres",
50
-
"uuid",
51
-
"tls-rustls", # Instead of default OpenSSL
52
-
] }
53
-
54
-
reqwest = { version = "0.12", default-features = false, features = [
55
-
"json",
56
-
"rustls-tls", # Instead of default native-tls
57
-
"stream",
58
-
"gzip",
59
-
] }
60
-
61
-
tokio-tungstenite = { version = "*", default-features = false, features = [
62
-
"rustls-tls-webpki-roots", # Instead of default native-tls
63
-
"connect", # For connect_async function
64
-
"handshake", # For accept_async function (tests)
65
-
] }
66
-
```
67
-
68
-
#### 2. Fixed Workspace Dependency Conflicts
69
-
The `services/Cargo.toml` was overriding workspace dependencies with different configurations. Fixed by:
70
-
- Changing `reqwest = { version = "0.12", features = ["json"] }` to `reqwest.workspace = true`
71
-
- Changing `tokio-tungstenite = "0.24"` to `tokio-tungstenite.workspace = true`
72
-
73
-
#### 3. Enhanced Cross.toml Configuration
74
-
Created comprehensive `Cross.toml` files for cross-compilation:
75
-
76
-
```toml
77
-
[build.env]
78
-
passthrough = [
79
-
"CARGO_HOME",
80
-
"CARGO_TARGET_DIR",
81
-
"SQLX_OFFLINE",
82
-
"PKG_CONFIG_ALLOW_CROSS",
83
-
]
84
-
85
-
[target.aarch64-unknown-linux-gnu]
86
-
image = "ghcr.io/cross-rs/aarch64-unknown-linux-gnu:main"
87
-
88
-
[target.aarch64-unknown-linux-gnu.env]
89
-
passthrough = ["CARGO_HOME", "CARGO_TARGET_DIR", "SQLX_OFFLINE"]
90
-
PKG_CONFIG_ALLOW_CROSS = "1"
91
-
RUSTFLAGS = "-C target-feature=+crt-static -C link-arg=-s"
92
-
CC_aarch64_unknown_linux_gnu = "aarch64-linux-gnu-gcc"
93
-
CXX_aarch64_unknown_linux_gnu = "aarch64-linux-gnu-g++"
94
-
```
95
-
96
-
#### 4. Improved CI Cross-Compilation
97
-
- Uses latest `cross` from Git: `cargo install cross --git https://github.com/cross-rs/cross`
98
-
- Sets `PKG_CONFIG_ALLOW_CROSS=1` environment variable
99
-
- Copies `.sqlx` files to individual service directories during cross-compilation
100
-
- Improved executable collection with better filtering
101
-
102
-
### Executable Collection
103
-
104
-
Enhanced executable collection in CI:
105
-
- Filters out build artifacts (`.d` files and temporary files with `-` in names)
106
-
- Handles missing target directories gracefully
107
-
- Collects executables for both x86_64 and aarch64 targets
108
-
- Provides clear logging of collected executables
109
-
110
-
## File Changes
111
-
112
-
### Created
113
-
- `scripts/setup-sqlx-offline.sh` - SQLx offline setup script
114
-
- `Cross.toml` - Root cross-compilation config
115
-
- `services/Cross.toml` - Services cross-compilation config
116
-
- `apps/aqua/Cross.toml` - Aqua cross-compilation config
117
-
118
-
### Modified
119
-
- `Cargo.toml` - Updated workspace dependencies to use rustls
120
-
- `services/Cargo.toml` - Fixed workspace dependency usage
121
-
- `.github/workflows/ci.yml` - Added SQLx setup and improved cross-compilation
122
-
123
-
## Usage
124
-
125
-
### Running SQLx Setup Locally
126
-
```bash
127
-
./scripts/setup-sqlx-offline.sh
128
-
```
129
-
130
-
### Cross-Compilation Locally
131
-
```bash
132
-
# Install cross if not already installed
133
-
cargo install cross --git https://github.com/cross-rs/cross
134
-
135
-
# Add target
136
-
rustup target add aarch64-unknown-linux-gnu
137
-
138
-
# Set environment
139
-
export PKG_CONFIG_ALLOW_CROSS=1
140
-
export SQLX_OFFLINE=true
141
-
142
-
# Run SQLx setup
143
-
./scripts/setup-sqlx-offline.sh
144
-
145
-
# Cross-compile services
146
-
cd services
147
-
cross build --release --target aarch64-unknown-linux-gnu
148
-
149
-
# Cross-compile apps
150
-
cd ../apps/aqua
151
-
cross build --release --target aarch64-unknown-linux-gnu
152
-
```
153
-
154
-
### Updating SQLx Queries
155
-
When you add or modify SQL queries:
156
-
157
-
1. Generate new query metadata from the services directory:
158
-
```bash
159
-
cd services
160
-
cargo sqlx prepare
161
-
```
162
-
163
-
2. Update all project copies:
164
-
```bash
165
-
./scripts/setup-sqlx-offline.sh
166
-
```
167
-
168
-
## Troubleshooting
169
-
170
-
### Cross-Compilation Still Fails
171
-
- Ensure you're using the latest `cross` from Git
172
-
- Check that `PKG_CONFIG_ALLOW_CROSS=1` is set
173
-
- Verify no dependencies are pulling in OpenSSL (use `cargo tree | grep openssl`)
174
-
175
-
### tokio-tungstenite Import Errors
176
-
If you see "unresolved import `tokio_tungstenite::connect_async`" errors:
177
-
- Ensure the `connect` feature is enabled for client functionality
178
-
- Add the `handshake` feature if using `accept_async` for server functionality
179
-
- Check that `default-features = false` is set to avoid OpenSSL dependencies
180
-
181
-
### tokio Module Errors
182
-
If you see "could not find `time` in `tokio`" or similar errors:
183
-
- Ensure tokio workspace dependency includes required features: `time`, `net`, `sync`
184
-
- These features are often included in default features but must be explicit when using `default-features = false`
185
-
186
-
### SQLx Offline Errors
187
-
- Run `./scripts/setup-sqlx-offline.sh` after any SQL query changes
188
-
- Ensure `.sqlx` directory exists in workspace root
189
-
- Check that `SQLX_OFFLINE=true` is set in CI environment
190
-
191
-
### Missing Executables
192
-
- Check that build succeeded without errors
193
-
- Verify executable names match expected service/app names
194
-
- Look for executables in `artifacts/` directory structure
195
-
196
-
## Dependencies Avoided
197
-
To maintain cross-compilation compatibility, avoid dependencies that:
198
-
- Default to OpenSSL (use rustls variants)
199
-
- Require system libraries not available in cross containers
200
-
- Have complex native build requirements
201
-
202
-
### Common Feature Configuration Issues
203
-
When disabling default features to avoid OpenSSL:
204
-
- `tokio`: Must explicitly enable `time`, `net`, `sync` features for common functionality
205
-
- `tokio-tungstenite`: Must explicitly enable `connect` and `handshake` features
206
-
- `reqwest`: Must explicitly enable required features like `json`, `stream`, `gzip`
207
-
- `sqlx`: Use `tls-rustls` instead of default OpenSSL TLS
208
-
209
-
Always test cross-compilation locally before pushing changes.
-355
docs/migration-troubleshooting.md
-355
docs/migration-troubleshooting.md
···
1
-
# Migration Troubleshooting Guide
2
-
3
-
## Common Migration Issues and Solutions
4
-
5
-
### Issue: "cannot drop function because other objects depend on it"
6
-
7
-
**Error Message:**
8
-
```
9
-
error: while executing migration 20241220000008: error returned from database: cannot drop function extract_discriminant(text) because other objects depend on it
10
-
```
11
-
12
-
**Cause:**
13
-
This error occurs when trying to drop database functions that have dependent objects (views, other functions, triggers, etc.) without properly handling the dependencies.
14
-
15
-
**Solution:**
16
-
17
-
#### Option 1: Fix the Migration (Recommended)
18
-
Update the problematic migration to handle dependencies properly:
19
-
20
-
1. **Edit the migration file** (e.g., `20241220000008_fix_discriminant_case_sensitivity.sql`):
21
-
22
-
```sql
23
-
-- Drop dependent views first, then functions, then recreate everything
24
-
DROP VIEW IF EXISTS discriminant_analysis CASCADE;
25
-
DROP VIEW IF EXISTS discriminant_stats CASCADE;
26
-
27
-
-- Drop existing functions with CASCADE to handle dependencies
28
-
DROP FUNCTION IF EXISTS extract_discriminant(TEXT) CASCADE;
29
-
DROP FUNCTION IF EXISTS get_base_name(TEXT) CASCADE;
30
-
DROP FUNCTION IF EXISTS extract_edition_discriminant(TEXT) CASCADE;
31
-
32
-
-- Then recreate functions and views...
33
-
```
34
-
35
-
2. **Reset the migration state** if the migration was partially applied:
36
-
37
-
```bash
38
-
# Connect to your database and reset the specific migration
39
-
psql $DATABASE_URL -c "DELETE FROM _sqlx_migrations WHERE version = '20241220000008';"
40
-
41
-
# Or reset all migrations and start fresh (WARNING: This drops all data)
42
-
psql $DATABASE_URL -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"
43
-
```
44
-
45
-
3. **Run migrations again**:
46
-
```bash
47
-
cd services
48
-
DATABASE_URL="your_database_url" sqlx migrate run
49
-
```
50
-
51
-
#### Option 2: Manual Dependency Cleanup
52
-
If you can't modify the migration file:
53
-
54
-
1. **Identify dependencies**:
55
-
```sql
56
-
-- Find objects that depend on the function
57
-
SELECT
58
-
p.proname as function_name,
59
-
d.objid,
60
-
d.classid::regclass as object_type,
61
-
d.refobjid
62
-
FROM pg_depend d
63
-
JOIN pg_proc p ON d.refobjid = p.oid
64
-
WHERE p.proname = 'extract_discriminant';
65
-
```
66
-
67
-
2. **Drop dependencies manually**:
68
-
```sql
69
-
-- Drop dependent views
70
-
DROP VIEW IF EXISTS discriminant_analysis CASCADE;
71
-
DROP VIEW IF EXISTS discriminant_stats CASCADE;
72
-
DROP VIEW IF EXISTS track_variants CASCADE;
73
-
DROP VIEW IF EXISTS release_variants CASCADE;
74
-
75
-
-- Drop the functions
76
-
DROP FUNCTION IF EXISTS extract_discriminant(TEXT) CASCADE;
77
-
DROP FUNCTION IF EXISTS get_base_name(TEXT) CASCADE;
78
-
DROP FUNCTION IF EXISTS extract_edition_discriminant(TEXT) CASCADE;
79
-
```
80
-
81
-
3. **Continue with migration**:
82
-
```bash
83
-
DATABASE_URL="your_database_url" sqlx migrate run
84
-
```
85
-
86
-
### Issue: "migration was previously applied but has been modified"
87
-
88
-
**Error Message:**
89
-
```
90
-
error: migration 20241220000008 was previously applied but has been modified
91
-
```
92
-
93
-
**Cause:**
94
-
The migration file has been changed after it was already applied to the database.
95
-
96
-
**Solutions:**
97
-
98
-
#### Option 1: Reset Migration State
99
-
```bash
100
-
# Remove the specific migration from tracking
101
-
psql $DATABASE_URL -c "DELETE FROM _sqlx_migrations WHERE version = '20241220000008';"
102
-
103
-
# Run migrations again
104
-
DATABASE_URL="your_database_url" sqlx migrate run
105
-
```
106
-
107
-
#### Option 2: Create a New Migration
108
-
```bash
109
-
# Create a new migration with your changes
110
-
sqlx migrate add fix_discriminant_case_sensitivity_v2
111
-
112
-
# Copy your changes to the new migration file
113
-
# Run the new migration
114
-
DATABASE_URL="your_database_url" sqlx migrate run
115
-
```
116
-
117
-
#### Option 3: Full Reset (WARNING: Destroys all data)
118
-
```bash
119
-
# Connect to database and reset everything
120
-
psql $DATABASE_URL -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"
121
-
122
-
# Run all migrations from scratch
123
-
DATABASE_URL="your_database_url" sqlx migrate run
124
-
```
125
-
126
-
### Issue: "No such file or directory" when running migrations
127
-
128
-
**Error Message:**
129
-
```
130
-
error: while resolving migrations: No such file or directory (os error 2)
131
-
```
132
-
133
-
**Cause:**
134
-
The migration directory is not found in the expected location.
135
-
136
-
**Solutions:**
137
-
138
-
#### Option 1: Check Migration Directory Location
139
-
```bash
140
-
# Check where sqlx expects migrations
141
-
cat services/.sqlx/.sqlxrc
142
-
143
-
# Ensure migrations exist in the correct location
144
-
ls -la services/migrations/
145
-
```
146
-
147
-
#### Option 2: Copy Migrations to Correct Location
148
-
```bash
149
-
# If migrations are in wrong location, copy them
150
-
cp migrations/*.sql services/migrations/
151
-
152
-
# Or create symlink
153
-
ln -s ../migrations services/migrations
154
-
```
155
-
156
-
#### Option 3: Update sqlx Configuration
157
-
Edit `services/.sqlx/.sqlxrc`:
158
-
```toml
159
-
[database]
160
-
url = "postgres://localhost/teal"
161
-
migrations = "../migrations" # Update path as needed
162
-
```
163
-
164
-
### Issue: Database Connection Problems
165
-
166
-
**Error Messages:**
167
-
- `Connection refused (os error 61)`
168
-
- `password authentication failed`
169
-
- `database "teal_test" does not exist`
170
-
171
-
**Solutions:**
172
-
173
-
#### Connection Refused
174
-
```bash
175
-
# Check if database is running
176
-
docker ps | grep postgres
177
-
178
-
# Start database if needed
179
-
docker-compose -f compose.db-test.yml up -d
180
-
181
-
# Wait for database to start
182
-
sleep 5
183
-
```
184
-
185
-
#### Authentication Issues
186
-
```bash
187
-
# Check connection string format
188
-
DATABASE_URL="postgres://username:password@host:port/database"
189
-
190
-
# Example for test database
191
-
DATABASE_URL="postgres://postgres:testpass123@localhost:5433/teal_test"
192
-
```
193
-
194
-
#### Database Doesn't Exist
195
-
```bash
196
-
# Create database
197
-
docker exec postgres_container psql -U postgres -c "CREATE DATABASE teal_test;"
198
-
199
-
# Or recreate test environment
200
-
docker-compose -f compose.db-test.yml down
201
-
docker-compose -f compose.db-test.yml up -d
202
-
```
203
-
204
-
## Migration Best Practices
205
-
206
-
### 1. Handle Dependencies Properly
207
-
Always use `CASCADE` when dropping objects with dependencies:
208
-
```sql
209
-
DROP FUNCTION function_name(args) CASCADE;
210
-
DROP VIEW view_name CASCADE;
211
-
```
212
-
213
-
### 2. Test Migrations Locally
214
-
```bash
215
-
# Use test database for migration testing
216
-
DATABASE_URL="postgres://localhost:5433/teal_test" sqlx migrate run
217
-
218
-
# Verify results
219
-
psql "postgres://localhost:5433/teal_test" -c "SELECT extract_discriminant('Test (Example)');"
220
-
```
221
-
222
-
### 3. Backup Before Major Migrations
223
-
```bash
224
-
# Create backup
225
-
pg_dump $DATABASE_URL > backup_before_migration.sql
226
-
227
-
# Apply migrations
228
-
sqlx migrate run
229
-
230
-
# Restore if needed
231
-
psql $DATABASE_URL < backup_before_migration.sql
232
-
```
233
-
234
-
### 4. Version Control Migration Files
235
-
- Never modify applied migrations
236
-
- Create new migrations for changes
237
-
- Use descriptive migration names
238
-
- Include rollback instructions in comments
239
-
240
-
### 5. Migration File Structure
241
-
```sql
242
-
-- Migration: descriptive_name
243
-
-- Purpose: Brief description of what this migration does
244
-
-- Dependencies: List any required prior migrations
245
-
-- Rollback: Instructions for manual rollback if needed
246
-
247
-
-- Drop dependencies first
248
-
DROP VIEW IF EXISTS dependent_view CASCADE;
249
-
250
-
-- Make changes
251
-
CREATE OR REPLACE FUNCTION new_function() ...;
252
-
253
-
-- Recreate dependencies
254
-
CREATE VIEW dependent_view AS ...;
255
-
256
-
-- Update existing data if needed
257
-
UPDATE table_name SET column = new_value WHERE condition;
258
-
259
-
-- Add comments
260
-
COMMENT ON FUNCTION new_function IS 'Description of function purpose';
261
-
```
262
-
263
-
## Emergency Recovery
264
-
265
-
### Complete Database Reset
266
-
If migrations are completely broken:
267
-
268
-
```bash
269
-
# 1. Stop all services
270
-
docker-compose down
271
-
272
-
# 2. Remove database volume (WARNING: Destroys all data)
273
-
docker volume rm teal_postgres_data
274
-
275
-
# 3. Start fresh
276
-
docker-compose up -d postgres
277
-
278
-
# 4. Wait for database to initialize
279
-
sleep 10
280
-
281
-
# 5. Run all migrations from scratch
282
-
DATABASE_URL="your_database_url" sqlx migrate run
283
-
```
284
-
285
-
### Partial Recovery
286
-
If only discriminant system is broken:
287
-
288
-
```sql
289
-
-- Remove discriminant-related objects
290
-
DROP VIEW IF EXISTS discriminant_analysis CASCADE;
291
-
DROP VIEW IF EXISTS discriminant_stats CASCADE;
292
-
DROP VIEW IF EXISTS track_variants CASCADE;
293
-
DROP VIEW IF EXISTS release_variants CASCADE;
294
-
DROP FUNCTION IF EXISTS extract_discriminant(TEXT) CASCADE;
295
-
DROP FUNCTION IF EXISTS get_base_name(TEXT) CASCADE;
296
-
DROP FUNCTION IF EXISTS extract_edition_discriminant(TEXT) CASCADE;
297
-
298
-
-- Remove discriminant columns
299
-
ALTER TABLE plays DROP COLUMN IF EXISTS track_discriminant;
300
-
ALTER TABLE plays DROP COLUMN IF EXISTS release_discriminant;
301
-
ALTER TABLE recordings DROP COLUMN IF EXISTS discriminant;
302
-
ALTER TABLE releases DROP COLUMN IF EXISTS discriminant;
303
-
304
-
-- Mark discriminant migrations as not applied
305
-
DELETE FROM _sqlx_migrations WHERE version >= '20241220000006';
306
-
307
-
-- Re-run discriminant migrations
308
-
```
309
-
310
-
## Getting Help
311
-
312
-
### Debug Information to Collect
313
-
When reporting migration issues, include:
314
-
315
-
1. **Error message** (full stack trace)
316
-
2. **Migration file content** that's causing issues
317
-
3. **Database state**:
318
-
```sql
319
-
SELECT version FROM _sqlx_migrations ORDER BY version;
320
-
\df extract_discriminant
321
-
\dv discriminant_*
322
-
```
323
-
4. **Environment details**:
324
-
- Database version: `SELECT version();`
325
-
- Operating system
326
-
- sqlx version: `cargo sqlx --version`
327
-
328
-
### Useful Debugging Commands
329
-
```sql
330
-
-- Check applied migrations
331
-
SELECT * FROM _sqlx_migrations ORDER BY version;
332
-
333
-
-- Check function definitions
334
-
\df+ extract_discriminant
335
-
336
-
-- Check view definitions
337
-
\d+ discriminant_analysis
338
-
339
-
-- Check table schemas
340
-
\d+ plays
341
-
\d+ recordings
342
-
\d+ releases
343
-
344
-
-- Test function directly
345
-
SELECT extract_discriminant('Test (Example)');
346
-
```
347
-
348
-
## Contact and Support
349
-
350
-
For persistent migration issues:
351
-
1. Check this troubleshooting guide first
352
-
2. Review the specific migration file causing issues
353
-
3. Try solutions in order of preference (fix migration → manual cleanup → reset)
354
-
4. Create minimal reproduction case for complex issues
355
-
5. Document exact steps that led to the error for support requests