Bladeren bron

refactor: Remove unnecessary migrations for fresh deployment

Remove old migration files entirely as they are not needed for first-time
deployment. The migrations were designed to upgrade an old database schema
(candles_1h -> candles, adding timeframe, etc.), but since this is a fresh
deployment, the Sequelize models already define the correct schema.

The models are the single source of truth:
- Candle model: includes timeframe, proper constraints and indexes
- Symbol model: includes all instrument types including 'index', proper indexes
- LivePrice model: properly defined

Database schema is created entirely by model sync on first deployment.
Future schema changes should be handled through new migrations if needed.
Hussain Afzal 3 maanden geleden
bovenliggende
commit
ba0b4a0aa3

+ 1 - 1
docker-compose.yml

@@ -59,7 +59,7 @@ services:
59 59
     restart: unless-stopped
60 60
     # Override entrypoint for development to use nodemon with live reload
61 61
     entrypoint: /bin/sh
62
-    command: -c "/usr/local/bin/wait-for-db.sh && node docker/sync-models.js && npx sequelize-cli db:migrate && npm install -g nodemon && nodemon src/server.js"
62
+    command: -c "/usr/local/bin/wait-for-db.sh && node docker/sync-models.js && (npx sequelize-cli db:migrate || echo 'No migrations to run or migration skipped') && npm install -g nodemon && nodemon src/server.js"
63 63
 
64 64
   # Nginx Reverse Proxy
65 65
   nginx:

+ 10 - 8
docker/entrypoint.sh

@@ -47,14 +47,16 @@ sequelize.sync({ alter: true, force: false })
47 47
     echo "WARNING: Model sync failed, continuing with migrations..."
48 48
 }
49 49
 
50
-# Run database migrations
51
-echo "Running database migrations..."
52
-npx sequelize-cli db:migrate || {
53
-    echo "ERROR: Database migration failed"
54
-    exit 1
55
-}
56
-
57
-echo "Migrations completed successfully"
50
+# Run database migrations (if any exist, excluding archive folder)
51
+echo "Running database migrations (if any)..."
52
+if [ -d "migrations" ] && [ "$(find migrations -maxdepth 1 -name '*.js' -not -path '*/archive/*' 2>/dev/null | wc -l)" -gt 0 ]; then
53
+    npx sequelize-cli db:migrate || {
54
+        echo "WARNING: Database migration failed, but continuing..."
55
+    }
56
+    echo "Migrations completed"
57
+else
58
+    echo "No migrations found, skipping migration step. Database schema created by model sync."
59
+fi
58 60
 
59 61
 # Start the application
60 62
 echo "Starting Node.js application..."

+ 0 - 41
migrations/20251016210526-add_unique_constraint_candles.js

@@ -1,41 +0,0 @@
1
-'use strict';
2
-
3
-/** @type {import('sequelize-cli').Migration} */
4
-module.exports = {
5
-  async up (queryInterface, Sequelize) {
6
-    // Check if table exists before adding constraint
7
-    const tableExists = await queryInterface.sequelize.query(
8
-      "SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_name = 'candles_1h');",
9
-      { type: Sequelize.QueryTypes.SELECT }
10
-    );
11
-    
12
-    if (tableExists && tableExists[0] && tableExists[0].exists) {
13
-      // Check if constraint already exists
14
-      const constraintExists = await queryInterface.sequelize.query(
15
-        "SELECT EXISTS (SELECT FROM pg_constraint WHERE conname = 'unique_symbol_open_time');",
16
-        { type: Sequelize.QueryTypes.SELECT }
17
-      );
18
-      
19
-      if (!constraintExists || !constraintExists[0] || !constraintExists[0].exists) {
20
-        await queryInterface.addConstraint('candles_1h', {
21
-          fields: ['symbol_id', 'open_time'],
22
-          type: 'unique',
23
-          name: 'unique_symbol_open_time'
24
-        });
25
-      }
26
-    } else {
27
-      console.log('Table candles_1h does not exist, skipping constraint addition. Tables will be created by model sync.');
28
-    }
29
-  },
30
-
31
-  async down (queryInterface, Sequelize) {
32
-    const tableExists = await queryInterface.sequelize.query(
33
-      "SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_name = 'candles_1h');",
34
-      { type: Sequelize.QueryTypes.SELECT }
35
-    );
36
-    
37
-    if (tableExists && tableExists[0] && tableExists[0].exists) {
38
-      await queryInterface.removeConstraint('candles_1h', 'unique_symbol_open_time');
39
-    }
40
-  }
41
-};

+ 0 - 33
migrations/20251027075914-add-index-to-instrument-type.js

@@ -1,33 +0,0 @@
1
-'use strict';
2
-
3
-/** @type {import('sequelize-cli').Migration} */
4
-module.exports = {
5
-  async up (queryInterface, Sequelize) {
6
-    // Check if table exists
7
-    const tableExists = await queryInterface.sequelize.query(
8
-      "SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_name = 'symbols');",
9
-      { type: Sequelize.QueryTypes.SELECT }
10
-    );
11
-    
12
-    if (tableExists && tableExists[0] && tableExists[0].exists) {
13
-      // Drop the existing CHECK constraint if it exists and add a new one with 'index'
14
-      await queryInterface.sequelize.query("ALTER TABLE symbols DROP CONSTRAINT IF EXISTS symbols_instrument_type_check;");
15
-      await queryInterface.sequelize.query("ALTER TABLE symbols ADD CONSTRAINT symbols_instrument_type_check CHECK (instrument_type IN ('crypto', 'stock', 'forex', 'commodity', 'index'));");
16
-    } else {
17
-      console.log('Table symbols does not exist, skipping constraint update. Tables will be created by model sync.');
18
-    }
19
-  },
20
-
21
-  async down (queryInterface, Sequelize) {
22
-    const tableExists = await queryInterface.sequelize.query(
23
-      "SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_name = 'symbols');",
24
-      { type: Sequelize.QueryTypes.SELECT }
25
-    );
26
-    
27
-    if (tableExists && tableExists[0] && tableExists[0].exists) {
28
-      // Revert the CHECK constraint without 'index'
29
-      await queryInterface.sequelize.query("ALTER TABLE symbols DROP CONSTRAINT IF EXISTS symbols_instrument_type_check;");
30
-      await queryInterface.sequelize.query("ALTER TABLE symbols ADD CONSTRAINT symbols_instrument_type_check CHECK (instrument_type IN ('crypto', 'stock', 'forex', 'commodity'));");
31
-    }
32
-  }
33
-};

+ 0 - 80
migrations/20251112102032-add-timeframe-to-candles.js

@@ -1,80 +0,0 @@
1
-'use strict';
2
-
3
-/** @type {import('sequelize-cli').Migration} */
4
-module.exports = {
5
-  async up (queryInterface, Sequelize) {
6
-    // Check if candles_1h table exists
7
-    const tableExists = await queryInterface.sequelize.query(
8
-      "SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_name = 'candles_1h');",
9
-      { type: Sequelize.QueryTypes.SELECT }
10
-    );
11
-    
12
-    if (!tableExists || !tableExists[0] || !tableExists[0].exists) {
13
-      console.log('Table candles_1h does not exist, skipping migration. Tables will be created by model sync with timeframe support.');
14
-      return;
15
-    }
16
-    
17
-    // Rename table from candles_1h to candles
18
-    await queryInterface.renameTable('candles_1h', 'candles');
19
-
20
-    // Add timeframe column with enum
21
-    await queryInterface.addColumn('candles', 'timeframe', {
22
-      type: Sequelize.ENUM('15m', '30m', '1h', '1D', '1W', '1M'),
23
-      allowNull: false,
24
-      defaultValue: '1h'
25
-    });
26
-
27
-    // Update existing records to have '1h' timeframe
28
-    await queryInterface.sequelize.query('UPDATE candles SET timeframe = \'1h\' WHERE timeframe IS NULL');
29
-
30
-    // Remove the default value after setting existing records
31
-    await queryInterface.changeColumn('candles', 'timeframe', {
32
-      type: Sequelize.ENUM('15m', '30m', '1h', '1D', '1W', '1M'),
33
-      allowNull: false
34
-    });
35
-
36
-    // Drop the old unique constraint
37
-    await queryInterface.removeConstraint('candles', 'unique_symbol_open_time');
38
-
39
-    // Add new unique constraint including timeframe
40
-    await queryInterface.addConstraint('candles', {
41
-      fields: ['symbol_id', 'open_time', 'timeframe'],
42
-      type: 'unique',
43
-      name: 'unique_symbol_open_time_timeframe'
44
-    });
45
-
46
-    // Update indexes to include timeframe
47
-    await queryInterface.removeIndex('candles', 'idx_candles_open_time');
48
-    await queryInterface.addIndex('candles', ['open_time', 'timeframe'], {
49
-      name: 'idx_candles_open_time_timeframe'
50
-    });
51
-  },
52
-
53
-  async down (queryInterface, Sequelize) {
54
-    // Reverse the changes
55
-
56
-    // Remove new indexes
57
-    await queryInterface.removeIndex('candles', 'idx_candles_open_time_timeframe');
58
-
59
-    // Add back old index
60
-    await queryInterface.addIndex('candles', ['open_time'], {
61
-      name: 'idx_candles_open_time'
62
-    });
63
-
64
-    // Remove new constraint
65
-    await queryInterface.removeConstraint('candles', 'unique_symbol_open_time_timeframe');
66
-
67
-    // Add back old constraint
68
-    await queryInterface.addConstraint('candles', {
69
-      fields: ['symbol_id', 'open_time'],
70
-      type: 'unique',
71
-      name: 'unique_symbol_open_time'
72
-    });
73
-
74
-    // Remove timeframe column
75
-    await queryInterface.removeColumn('candles', 'timeframe');
76
-
77
-    // Rename table back to candles_1h
78
-    await queryInterface.renameTable('candles', 'candles_1h');
79
-  }
80
-};