瀏覽代碼

feat: Add candle cleanup endpoint for data management

- Add DELETE /api/candles/cleanup/:symbolId endpoint
- Implement cleanupCandles controller method with smart retention logic
- Keep latest N candles (default 1000) and delete older ones
- Include proper validation and error handling
- Return detailed cleanup statistics (deleted/kept counts)
- Support configurable retention via ?keep=N query parameter
uzairrizwan1 9 月之前
父節點
當前提交
cd8b38a13a
共有 2 個文件被更改,包括 66 次插入0 次删除
  1. 59 0
      src/controllers/candleController.js
  2. 7 0
      src/routes/candles.js

+ 59 - 0
src/controllers/candleController.js

@@ -206,6 +206,65 @@ class CandleController {
       next(error);
     }
   }
+
+  // Clean up old candles, keep latest N candles
+  async cleanupCandles(req, res, next) {
+    try {
+      const { symbolId } = req.params;
+      const { keep = 1000 } = req.query;
+
+      // Verify symbol exists
+      const symbol = await Symbol.findByPk(symbolId);
+      if (!symbol) {
+        const error = new Error('Symbol not found');
+        error.statusCode = 404;
+        return next(error);
+      }
+
+      // Get total count of candles for this symbol
+      const totalCandles = await Candle1h.count({
+        where: { symbolId: parseInt(symbolId) }
+      });
+
+      if (totalCandles <= keep) {
+        return res.json({
+          success: true,
+          message: `No cleanup needed. Only ${totalCandles} candles exist (keep: ${keep})`,
+          deletedCount: 0
+        });
+      }
+
+      // Get the IDs of candles to keep (latest N candles)
+      const candlesToKeep = await Candle1h.findAll({
+        where: { symbolId: parseInt(symbolId) },
+        order: [['openTime', 'DESC']],
+        limit: parseInt(keep),
+        attributes: ['id']
+      });
+
+      const keepIds = candlesToKeep.map(candle => candle.id);
+
+      // Delete older candles (those not in keepIds)
+      const deletedCount = await Candle1h.destroy({
+        where: {
+          symbolId: parseInt(symbolId),
+          id: {
+            [Op.notIn]: keepIds
+          }
+        }
+      });
+
+      res.json({
+        success: true,
+        message: `Cleanup completed. Deleted ${deletedCount} old candles, kept ${keepIds.length} latest candles`,
+        deletedCount,
+        keptCount: keepIds.length,
+        symbol: symbol.symbol
+      });
+    } catch (error) {
+      next(error);
+    }
+  }
 }
 
 module.exports = new CandleController();

+ 7 - 0
src/routes/candles.js

@@ -58,4 +58,11 @@ router.post('/bulk', validate(Joi.object({
   })).min(1).required()
 })), candleController.bulkCreateCandles);
 
+// DELETE /api/candles/cleanup/:symbolId - Clean up old candles, keep latest N
+router.delete('/cleanup/:symbolId', validateParams(Joi.object({
+  symbolId: Joi.number().integer().positive().required()
+})), validateQuery(Joi.object({
+  keep: Joi.number().integer().min(1).default(1000)
+})), candleController.cleanupCandles);
+
 module.exports = router;