> ## Documentation Index
> Fetch the complete documentation index at: https://hyrex.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Maintenance Tasks

> Automate database backups, file cleanup, and system maintenance

Build reliable background tasks for common maintenance operations like database backups, file cleanup, analytics reporting, and media processing.

## Overview

This example demonstrates how to automate essential maintenance tasks:

* **Database backups** with S3 storage
* **File cleanup** for temp files and logs
* **Analytics reporting** with email notifications
* **Video thumbnail generation** for media assets
* **Scheduled cron jobs** for recurring maintenance

Perfect for keeping your production systems clean, backed up, and monitored.

## Task Definitions

<CodeGroup>
  ```python Python theme={null}
  from hyrex import HyrexRegistry
  from datetime import datetime, timedelta
  import requests
  import os

  hy = HyrexRegistry()

  @hy.task
  def send_daily_report_email(recipient_email: str, report_data: dict):
      """Send daily analytics report via email"""
      date_str = datetime.now().strftime('%Y-%m-%d')
      email_content = f"Daily Analytics Report - {date_str}\\n\\n"
      email_content += f"Active Users: {report_data['active_users']}\\n"
      email_content += f"Revenue: ${report_data['revenue']:,.2f}\\n"
      email_content += f"New Signups: {report_data['new_signups']}\\n"
      email_content += f"Support Tickets: {report_data['support_tickets']}\\n\\n"
      email_content += "View full dashboard: https://yourapp.com/analytics"
      
      send_email(
          to=recipient_email,
          subject=f"Daily Report - {datetime.now().strftime('%m/%d/%Y')}",
          body=email_content
      )

  @hy.task
  def backup_database(database_name: str, s3_bucket: str):
      """Create database backup and upload to S3"""
      timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
      backup_filename = f"{database_name}_{timestamp}.sql"
      
      # Create database dump
      os.system(f"pg_dump {database_name} > /tmp/{backup_filename}")
      
      # Upload to S3
      upload_to_s3(f"/tmp/{backup_filename}", s3_bucket, f"backups/{backup_filename}")
      
      # Clean up local file
      os.remove(f"/tmp/{backup_filename}")
      
      return {"backup_file": backup_filename, "size_mb": get_file_size_mb(backup_filename)}

  @hy.task
  def cleanup_old_files(directory: str, days_old: int = 30):
      """Remove files older than specified days"""
      cutoff_date = datetime.now() - timedelta(days=days_old)
      removed_files = []
      
      for filename in os.listdir(directory):
          file_path = os.path.join(directory, filename)
          if os.path.isfile(file_path):
              file_modified = datetime.fromtimestamp(os.path.getmtime(file_path))
              if file_modified < cutoff_date:
                  os.remove(file_path)
                  removed_files.append(filename)
      
      return {"removed_files": removed_files, "count": len(removed_files)}

  @hy.task
  def process_video_thumbnail(video_url: str, output_bucket: str):
      """Generate video thumbnail and upload to storage"""
      import cv2
      import tempfile
      
      # Download video to temp file
      video_response = requests.get(video_url)
      with tempfile.NamedTemporaryFile(suffix='.mp4') as temp_video:
          temp_video.write(video_response.content)
          temp_video.flush()
          
          # Extract frame at 2 seconds
          cap = cv2.VideoCapture(temp_video.name)
          cap.set(cv2.CAP_PROP_POS_MSEC, 2000)  # 2 seconds
          ret, frame = cap.read()
          
          if ret:
              thumbnail_filename = f"thumb_{hash(video_url)}.jpg"
              with tempfile.NamedTemporaryFile(suffix='.jpg') as temp_thumb:
                  cv2.imwrite(temp_thumb.name, frame)
                  upload_to_s3(temp_thumb.name, output_bucket, f"thumbnails/{thumbnail_filename}")
                  
          cap.release()
          
      return {"thumbnail_url": f"s3://{output_bucket}/thumbnails/{thumbnail_filename}"}

  @hy.task
  def generate_analytics_report():
      """Generate daily analytics data"""
      report_data = {
          "active_users": get_active_users_count(),
          "revenue": get_daily_revenue(),
          "new_signups": get_new_signups_count(),
          "support_tickets": get_open_tickets_count()
      }
      
      # Store in database
      store_daily_metrics(report_data)
      
      # Send to stakeholders
      stakeholder_emails = ["ceo@company.com", "cto@company.com", "head-of-product@company.com"]
      for email in stakeholder_emails:
          send_daily_report_email.send(email, report_data)
      
      return report_data

  # Schedule recurring tasks
  @hy.cron("0 9 * * *")  # Every day at 9 AM
  def daily_tasks():
      """Run daily maintenance tasks"""
      generate_analytics_report.send()
      backup_database.send("production_db", "company-backups")
      cleanup_old_files.send("/app/temp", 7)  # Clean files older than 7 days

  @hy.cron("0 2 * * 0")  # Every Sunday at 2 AM
  def weekly_tasks():
      """Run weekly maintenance tasks"""
      cleanup_old_files.send("/app/logs", 30)  # Clean logs older than 30 days
      backup_database.send("analytics_db", "company-backups")
  ```

  ```typescript TypeScript theme={null}
  import { HyrexRegistry } from 'hyrex';
  import axios from 'axios';
  import fs from 'fs';
  import path from 'path';

  const hy = new HyrexRegistry();

  const sendDailyReportEmail = hy.task({
      name: "sendDailyReportEmail",
      func: async (recipientEmail: string, reportData: any) => {
          const dateStr = new Date().toISOString().split('T')[0];
          let emailContent = `Daily Analytics Report - ${dateStr}\\n\\n`;
          emailContent += `Active Users: ${reportData.activeUsers}\\n`;
          emailContent += `Revenue: $${reportData.revenue.toLocaleString()}\\n`;
          emailContent += `New Signups: ${reportData.newSignups}\\n`;
          emailContent += `Support Tickets: ${reportData.supportTickets}\\n\\n`;
          emailContent += 'View full dashboard: https://yourapp.com/analytics';
          
          await sendEmail({
              to: recipientEmail,
              subject: `Daily Report - ${new Date().toLocaleDateString()}`,
              body: emailContent
          });
      }
  });

  const backupDatabase = hy.task({
      name: "backupDatabase",
      func: async (databaseName: string, s3Bucket: string) => {
          const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
          const backupFilename = `${databaseName}_${timestamp}.sql`;
          const tempPath = `/tmp/${backupFilename}`;
          
          // Create database dump
          await execCommand(`pg_dump ${databaseName} > ${tempPath}`);
          
          // Upload to S3
          await uploadToS3(tempPath, s3Bucket, `backups/${backupFilename}`);
          
          // Clean up local file
          fs.unlinkSync(tempPath);
          
          const stats = fs.statSync(tempPath);
          return { 
              backupFile: backupFilename, 
              sizeMb: Math.round(stats.size / 1024 / 1024) 
          };
      }
  });

  const cleanupOldFiles = hy.task({
      name: "cleanupOldFiles",
      func: async (directory: string, daysOld: number = 30) => {
          const cutoffDate = new Date();
          cutoffDate.setDate(cutoffDate.getDate() - daysOld);
          
          const removedFiles: string[] = [];
          
          const files = fs.readdirSync(directory);
          for (const filename of files) {
              const filePath = path.join(directory, filename);
              const stats = fs.statSync(filePath);
              
              if (stats.isFile() && stats.mtime < cutoffDate) {
                  fs.unlinkSync(filePath);
                  removedFiles.push(filename);
              }
          }
          
          return { removedFiles, count: removedFiles.length };
      }
  });

  const processVideoThumbnail = hy.task({
      name: "processVideoThumbnail",
      func: async (videoUrl: string, outputBucket: string) => {
          const ffmpeg = require('fluent-ffmpeg');
          const crypto = require('crypto');
          
          const hash = crypto.createHash('md5').update(videoUrl).digest('hex');
          const thumbnailFilename = `thumb_${hash}.jpg`;
          const tempPath = `/tmp/${thumbnailFilename}`;
          
          // Extract thumbnail at 2 seconds
          await new Promise((resolve, reject) => {
              ffmpeg(videoUrl)
                  .seekInput(2)
                  .frames(1)
                  .output(tempPath)
                  .on('end', resolve)
                  .on('error', reject)
                  .run();
          });
          
          // Upload to S3
          await uploadToS3(tempPath, outputBucket, `thumbnails/${thumbnailFilename}`);
          
          // Clean up
          fs.unlinkSync(tempPath);
          
          return { 
              thumbnailUrl: `s3://${outputBucket}/thumbnails/${thumbnailFilename}`
          };
      }
  });

  const generateAnalyticsReport = hy.task({
      name: "generateAnalyticsReport",
      func: async () => {
          const reportData = {
              activeUsers: await getActiveUsersCount(),
              revenue: await getDailyRevenue(),
              newSignups: await getNewSignupsCount(),
              supportTickets: await getOpenTicketsCount()
          };
          
          // Store in database
          await storeDailyMetrics(reportData);
          
          // Send to stakeholders
          const stakeholderEmails = [
              "ceo@company.com", 
              "cto@company.com", 
              "head-of-product@company.com"
          ];
          
          for (const email of stakeholderEmails) {
              await sendDailyReportEmail.send(email, reportData);
          }
          
          return reportData;
      }
  });

  // Schedule recurring tasks
  const dailyTasks = hy.cron({
      schedule: "0 9 * * *", // Every day at 9 AM
      name: "dailyTasks",
      func: async () => {
          await generateAnalyticsReport.send();
          await backupDatabase.send("production_db", "company-backups");
          await cleanupOldFiles.send("/app/temp", 7); // Clean files older than 7 days
      }
  });

  const weeklyTasks = hy.cron({
      schedule: "0 2 * * 0", // Every Sunday at 2 AM
      name: "weeklyTasks", 
      func: async () => {
          await cleanupOldFiles.send("/app/logs", 30); // Clean logs older than 30 days
          await backupDatabase.send("analytics_db", "company-backups");
      }
  });
  ```
</CodeGroup>

## REST API Endpoints

Provide on-demand task triggering through REST endpoints:

<CodeGroup>
  ```python Python (FastAPI) theme={null}
  from fastapi import FastAPI
  from pydantic import BaseModel
  from .tasks import backup_database, cleanup_old_files, process_video_thumbnail

  app = FastAPI()

  class BackupRequest(BaseModel):
      database_name: str
      s3_bucket: str
      
  class CleanupRequest(BaseModel):
      directory: str
      days_old: int = 30
      
  class VideoProcessRequest(BaseModel):
      video_url: str
      output_bucket: str

  @app.post("/tasks/backup")
  async def trigger_backup(request: BackupRequest):
      """Trigger database backup"""
      task = backup_database.send(request.database_name, request.s3_bucket)
      
      return {
          "message": "Backup task started",
          "task_id": task.task_id,
          "database": request.database_name
      }

  @app.post("/tasks/cleanup")
  async def trigger_cleanup(request: CleanupRequest):
      """Trigger file cleanup"""
      task = cleanup_old_files.send(request.directory, request.days_old)
      
      return {
          "message": "Cleanup task started",
          "task_id": task.task_id,
          "directory": request.directory
      }

  @app.post("/tasks/process-video")
  async def process_video(request: VideoProcessRequest):
      """Process video thumbnail generation"""
      task = process_video_thumbnail.send(request.video_url, request.output_bucket)
      
      return {
          "message": "Video processing started",
          "task_id": task.task_id,
          "video_url": request.video_url
      }

  @app.get("/tasks/status/{task_id}")
  async def get_task_status(task_id: str):
      """Get status of background task"""
      task = hy.get_task(task_id)
      
      return {
          "task_id": task_id,
          "status": task.status,
          "progress": task.progress,
          "result": task.result if task.is_complete else None,
          "created_at": task.created_at,
          "completed_at": task.completed_at
      }
  ```

  ```typescript TypeScript (Express) theme={null}
  import express from 'express';
  import { backupDatabase, cleanupOldFiles, processVideoThumbnail } from './tasks';

  const app = express();
  app.use(express.json());

  interface BackupRequest {
      databaseName: string;
      s3Bucket: string;
  }

  interface CleanupRequest {
      directory: string;
      daysOld?: number;
  }

  interface VideoProcessRequest {
      videoUrl: string;
      outputBucket: string;
  }

  app.post('/tasks/backup', async (req, res) => {
      const { databaseName, s3Bucket }: BackupRequest = req.body;
      
      // Trigger database backup
      const task = await backupDatabase.send(databaseName, s3Bucket);
      
      res.json({
          message: 'Backup task started',
          taskId: task.taskId,
          database: databaseName
      });
  });

  app.post('/tasks/cleanup', async (req, res) => {
      const { directory, daysOld = 30 }: CleanupRequest = req.body;
      
      // Trigger file cleanup
      const task = await cleanupOldFiles.send(directory, daysOld);
      
      res.json({
          message: 'Cleanup task started',
          taskId: task.taskId,
          directory: directory
      });
  });

  app.post('/tasks/process-video', async (req, res) => {
      const { videoUrl, outputBucket }: VideoProcessRequest = req.body;
      
      // Process video thumbnail generation
      const task = await processVideoThumbnail.send(videoUrl, outputBucket);
      
      res.json({
          message: 'Video processing started',
          taskId: task.taskId,
          videoUrl: videoUrl
      });
  });

  app.get('/tasks/status/:taskId', async (req, res) => {
      const { taskId } = req.params;
      
      // Get status of background task
      const task = await hy.getTask(taskId);
      
      res.json({
          taskId: taskId,
          status: task.status,
          progress: task.progress,
          result: task.isComplete ? task.result : null,
          createdAt: task.createdAt,
          completedAt: task.completedAt
      });
  });
  ```
</CodeGroup>

## Usage Examples

### Trigger Tasks via API

```bash theme={null}
# Backup production database
curl -X POST http://localhost:8000/tasks/backup \
  -H "Content-Type: application/json" \
  -d '{
    "database_name": "production_db",
    "s3_bucket": "company-backups"
  }'

# Clean up old temp files
curl -X POST http://localhost:8000/tasks/cleanup \
  -H "Content-Type: application/json" \
  -d '{
    "directory": "/app/temp",
    "days_old": 7
  }'

# Generate video thumbnail
curl -X POST http://localhost:8000/tasks/process-video \
  -H "Content-Type: application/json" \
  -d '{
    "video_url": "https://example.com/video.mp4",
    "output_bucket": "media-thumbnails"
  }'

# Check task status
curl http://localhost:8000/tasks/status/12345
```

### Monitor Scheduled Tasks

Cron jobs run automatically but you can monitor them through Hyrex Studio:

* **Daily tasks** run every morning at 9 AM
* **Weekly tasks** run every Sunday at 2 AM
* View execution history and performance metrics
* Set up alerts for failed tasks

## Cron Schedule Reference

| Schedule         | Description             | Example         |
| ---------------- | ----------------------- | --------------- |
| `"0 9 * * *"`    | Daily at 9 AM           | Daily reports   |
| `"0 2 * * 0"`    | Weekly Sunday 2 AM      | Weekly cleanup  |
| `"0 0 1 * *"`    | Monthly 1st at midnight | Monthly billing |
| `"*/15 * * * *"` | Every 15 minutes        | Health checks   |
| `"0 */6 * * *"`  | Every 6 hours           | Log rotation    |

## Production Considerations

* **Backup retention**: Implement S3 lifecycle policies to archive old backups
* **Error handling**: Set up alerts for failed maintenance tasks
* **Resource usage**: Schedule heavy tasks during low-traffic periods
* **Monitoring**: Track backup sizes, cleanup counts, and processing times
* **Security**: Use IAM roles for S3 access, secure database credentials

## Next Steps

<CardGroup cols={2}>
  <Card title="Error Handling" href="/docs/examples/monitoring/error-handling" icon="triangle-exclamation">
    Handle failures and implement retry logic
  </Card>

  <Card title="Production Guide" href="/docs/examples/production-guide" icon="rocket">
    Deploy maintenance tasks at scale
  </Card>
</CardGroup>
