Skip to content

Latest commit

Β 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

PyJob - Python Job Scheduler

A Node.js-based job scheduler that executes Python scripts in isolated virtual environments with CRON-like scheduling capabilities.

Features

  • Isolated Python Environments: Each job runs in its own virtual environment
  • CRON Scheduling: Schedule jobs using standard CRON patterns
  • Security: Python jobs are restricted to API calls and logging only
  • NoSQL Storage: MongoDB-based storage for job configurations
  • REST API: Full CRUD API for managing jobs
  • Authentication: JWT tokens, API keys, and Basic Auth support
  • User Management: Role-based access control (admin/user)
  • Automatic Cleanup: Virtual environments are automatically removed after execution
  • Comprehensive Logging: Detailed logging of job execution and errors
  • Manual Execution: Execute jobs on-demand via API
  • Rate Limiting: Built-in protection against abuse
  • Search & Statistics: Advanced job search and system statistics

Prerequisites

  • Node.js 18+
  • Python 3.7+
  • MongoDB
  • npm or yarn

Installation

  1. Clone the repository:
git clone <repository-url>
cd pyjob
  1. Install dependencies:
npm install
  1. Set up environment variables:
cp env.example .env
# Edit .env with your configuration
  1. Start MongoDB (if running locally):
mongod
  1. Create an admin user:
npm run create-admin
  1. Start the application:
# Development
npm run dev

# Production
npm start

Configuration

Environment Variables

Variable Description Default
MONGODB_URI MongoDB connection string mongodb://localhost:27017/pyjob
PORT Server port 3000
NODE_ENV Environment mode development
PYTHON_BASE_PATH Base path for virtual environments /tmp/pyjob-envs
MAX_CONCURRENT_JOBS Maximum concurrent job executions 5
LOG_LEVEL Logging level info

API Endpoints

Authentication

  • POST /api/auth/register - Register new user
  • POST /api/auth/login - Login with username/password
  • POST /api/auth/token - Get JWT token (Basic Auth)
  • GET /api/auth/me - Get current user info
  • POST /api/auth/api-keys - Generate API key
  • GET /api/auth/api-keys - List API keys
  • DELETE /api/auth/api-keys/:name - Revoke API key

Jobs

  • GET /api/jobs - List all jobs (public read)
  • GET /api/jobs/:id - Get job by ID (public read)
  • POST /api/jobs - Create new job (auth required)
  • PUT /api/jobs/:id - Update job (auth required)
  • DELETE /api/jobs/:id - Delete job (auth required)
  • POST /api/jobs/:id/execute - Execute job manually (auth required)
  • PATCH /api/jobs/:id/toggle - Toggle job status (auth required)
  • GET /api/jobs/:id/executions - Get job execution history (auth required)
  • GET /api/jobs/:id/logs - Get job logs (auth required)
  • GET /api/jobs/search - Search jobs (public)
  • GET /api/jobs/stats/overview - Get statistics (public)
  • GET /api/jobs/scheduled/status - Get scheduled jobs status (auth required)
  • GET /api/jobs/export - Export jobs data (admin only)

System

  • GET /health - Health check
  • GET /api/jobs/health/status - System health status
  • GET / - API information

Job Configuration

Job Schema

{
  "name": "my-python-job",
  "description": "A sample Python job",
  "cronPattern": "0 */6 * * *",
  "pythonScript": "print('Hello from Python!')",
  "requirements": ["requests", "numpy"],
  "environmentVariables": {
    "API_KEY": "your-api-key",
    "DEBUG": "true"
  },
  "isActive": true,
  "timeout": 300000,
  "maxRetries": 3
}

CRON Pattern Format

Standard 5-field CRON pattern:

* * * * *
β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ β”‚ β”‚ β”‚ └─── Day of week (0-6)
β”‚ β”‚ β”‚ └───── Month (1-12)
β”‚ β”‚ └─────── Day of month (1-31)
β”‚ └───────── Hour (0-23)
└─────────── Minute (0-59)

Examples:

  • 0 */6 * * * - Every 6 hours
  • 0 9 * * 1-5 - Every weekday at 9 AM
  • */15 * * * * - Every 15 minutes

πŸ“š Complete User Guide

This comprehensive guide covers all aspects of using PyJob, from account creation to advanced job management with different authentication methods.

πŸ” Authentication Methods

PyJob supports three authentication methods:

  1. JWT Token Authentication - For web applications and API clients
  2. API Key Authentication - For programmatic access and integrations
  3. Basic Authentication - For simple HTTP clients

πŸ‘€ Account Management

Creating Your First Account

Method 1: Using the Admin Script (Recommended for First User)

The easiest way to get started is to create an admin account using the provided script:

# Run the admin creation script
npm run create-admin

This will create an admin user with the following default credentials:

  • Username: admin
  • Email: admin@pyjob.local
  • Password: admin123
  • Role: admin

⚠️ Important: Change these credentials after first login!

Method 2: Register via API

You can register new users through the API. Here are examples for all authentication methods:

Using JWT Token Authentication
# 1. Register a new user
curl -X POST http://localhost:3000/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "username": "john_doe",
    "email": "john@example.com",
    "password": "securepassword123",
    "role": "user"
  }'

# Response:
# {
#   "message": "User registered successfully",
#   "user": {
#     "id": "68ca6ea99ad4c9a6fa530bee",
#     "username": "john_doe",
#     "email": "john@example.com",
#     "role": "user",
#     "isActive": true,
#     "createdAt": "2025-09-17T08:15:02.560Z"
#   }
# }
Using Basic Authentication
# Register using Basic Auth (username:password in base64)
curl -X POST http://localhost:3000/api/auth/register \
  -H "Content-Type: application/json" \
  -H "Authorization: Basic $(echo -n 'admin:admin123' | base64)" \
  -d '{
    "username": "jane_doe",
    "email": "jane@example.com",
    "password": "securepassword123",
    "role": "user"
  }'

Logging In

JWT Token Login

# Login and get JWT token
curl -X POST http://localhost:3000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "username": "john_doe",
    "password": "securepassword123"
  }'

# Response:
# {
#   "message": "Login successful",
#   "user": {
#     "id": "68ca6ea99ad4c9a6fa530bee",
#     "username": "john_doe",
#     "email": "john@example.com",
#     "role": "user",
#     "lastLogin": "2025-09-17T08:15:32.490Z"
#   },
#   "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
# }

Basic Authentication Login

# Get JWT token using Basic Auth
curl -X POST http://localhost:3000/api/auth/token \
  -H "Authorization: Basic $(echo -n 'john_doe:securepassword123' | base64)"

# Response:
# {
#   "message": "Token generated successfully",
#   "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
#   "expiresIn": "24h"
# }

API Key Management

API keys are perfect for programmatic access and integrations:

Generate API Key

# Generate a new API key (requires authentication)
curl -X POST http://localhost:3000/api/auth/api-keys \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-integration-key"
  }'

# Response:
# {
#   "message": "API key generated successfully",
#   "apiKey": {
#     "name": "my-integration-key",
#     "key": "pyjob_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
#     "createdAt": "2025-09-17T08:15:32.490Z"
#   }
# }

List API Keys

# List all your API keys
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  http://localhost:3000/api/auth/api-keys

# Response:
# {
#   "apiKeys": [
#     {
#       "name": "my-integration-key",
#       "key": "pyjob_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
#       "createdAt": "2025-09-17T08:15:32.490Z"
#     }
#   ]
# }

Revoke API Key

# Revoke an API key
curl -X DELETE http://localhost:3000/api/auth/api-keys/my-integration-key \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

JWT Token Management

PyJob now supports comprehensive JWT token management, allowing users to create, manage, and track multiple tokens with descriptions and expiration control.

Generate JWT Token

# Generate a new JWT token with description
curl -X POST http://localhost:3000/api/auth/tokens \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "API integration token for mobile app"
  }'

# Response:
# {
#   "message": "JWT token generated successfully",
#   "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
#   "tokenInfo": {
#     "tokenId": "18019b9a-0eb9-48ba-ab49-104d4df531cb",
#     "description": "API integration token for mobile app",
#     "expiresAt": "2025-09-18T08:33:58.342Z",
#     "createdAt": "2025-09-17T08:33:58.347Z"
#   }
# }

List JWT Tokens

# List all your JWT tokens
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  http://localhost:3000/api/auth/tokens

# Response:
# {
#   "tokens": [
#     {
#       "tokenId": "18019b9a-0eb9-48ba-ab49-104d4df531cb",
#       "description": "API integration token for mobile app",
#       "createdAt": "2025-09-17T08:33:58.343Z",
#       "lastUsed": "2025-09-17T10:34:11.000Z",
#       "expiresAt": "2025-09-20T08:33:58.342Z",
#       "isActive": true,
#       "isExpired": false
#     }
#   ]
# }

Get Specific Token Info

# Get details for a specific token
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  http://localhost:3000/api/auth/tokens/18019b9a-0eb9-48ba-ab49-104d4df531cb

# Response:
# {
#   "tokenId": "18019b9a-0eb9-48ba-ab49-104d4df531cb",
#   "description": "API integration token for mobile app",
#   "createdAt": "2025-09-17T08:33:58.343Z",
#   "lastUsed": "2025-09-17T10:34:11.000Z",
#   "expiresAt": "2025-09-20T08:33:58.342Z",
#   "isActive": true,
#   "isExpired": false
# }

Update Token Description

# Update token description
curl -X PUT http://localhost:3000/api/auth/tokens/18019b9a-0eb9-48ba-ab49-104d4df531cb/description \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Updated description - Production API token"
  }'

Extend Token Expiration

# Extend token expiration by 48 hours
curl -X POST http://localhost:3000/api/auth/tokens/18019b9a-0eb9-48ba-ab49-104d4df531cb/extend \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "additionalHours": 48
  }'

# Response:
# {
#   "message": "Token expiration extended successfully",
#   "newExpiresAt": "2025-09-20T08:33:58.342Z"
# }

Revoke JWT Token

# Revoke a JWT token
curl -X DELETE http://localhost:3000/api/auth/tokens/18019b9a-0eb9-48ba-ab49-104d4df531cb \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Clean Up Expired Tokens

# Clean up expired tokens
curl -X POST http://localhost:3000/api/auth/tokens/cleanup \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

# Response:
# {
#   "message": "Token cleanup completed",
#   "cleanedCount": 3,
#   "remainingTokens": 2
# }

πŸš€ Job Management Guide

Creating Jobs

Jobs can be created using any of the three authentication methods. Here are complete examples:

Using JWT Token Authentication

# Set your JWT token (replace with actual token)
export JWT_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

# Create a simple Python job
curl -X POST http://localhost:3000/api/jobs \
  -H "Authorization: Bearer $JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Hello World Job",
    "description": "A simple job that prints hello world every 5 minutes",
    "cronPattern": "*/5 * * * *",
    "pythonScript": "print(\"Hello from PyJob!\")\nprint(\"Current time:\", __import__(\"datetime\").datetime.now())",
    "requirements": [],
    "environmentVariables": {
      "ENVIRONMENT": "production"
    },
    "isActive": true,
    "timeout": 300000,
    "maxRetries": 3
  }'

# Response:
# {
#   "name": "Hello World Job",
#   "description": "A simple job that prints hello world every 5 minutes",
#   "cronPattern": "*/5 * * * *",
#   "pythonScript": "print(\"Hello from PyJob!\")\nprint(\"Current time:\", __import__(\"datetime\").datetime.now())",
#   "requirements": [],
#   "environmentVariables": {
#     "ENVIRONMENT": "production"
#   },
#   "isActive": true,
#   "runCount": 0,
#   "successCount": 0,
#   "failureCount": 0,
#   "timeout": 300000,
#   "maxRetries": 3,
#   "_id": "68ca6ea99ad4c9a6fa530bee",
#   "createdAt": "2025-09-17T08:17:45.473Z",
#   "updatedAt": "2025-09-17T08:17:45.474Z",
#   "__v": 0
# }

Using API Key Authentication

# Set your API key (replace with actual key)
export API_KEY="pyjob_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"

# Create a data processing job
curl -X POST http://localhost:3000/api/jobs \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Data Processor",
    "description": "Process data from external API every hour",
    "cronPattern": "0 * * * *",
    "pythonScript": "import requests\nimport json\n\n# Fetch data from API\nresponse = requests.get(\"https://api.example.com/data\")\ndata = response.json()\n\n# Process the data\nprocessed_data = {\n    \"timestamp\": __import__(\"datetime\").datetime.now().isoformat(),\n    \"count\": len(data),\n    \"status\": \"processed\"\n}\n\nprint(json.dumps(processed_data, indent=2))",
    "requirements": ["requests"],
    "environmentVariables": {
      "API_URL": "https://api.example.com",
      "API_KEY": "your-secret-api-key"
    },
    "isActive": true,
    "timeout": 600000,
    "maxRetries": 2
  }'

Using Basic Authentication

# Create a monitoring job using Basic Auth
curl -X POST http://localhost:3000/api/jobs \
  -H "Authorization: Basic $(echo -n 'john_doe:securepassword123' | base64)" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "System Monitor",
    "description": "Monitor system health every 15 minutes",
    "cronPattern": "*/15 * * * *",
    "pythonScript": "import psutil\nimport json\n\n# Get system information\ncpu_percent = psutil.cpu_percent(interval=1)\nmemory = psutil.virtual_memory()\ndisk = psutil.disk_usage(\"/\")\n\n# Create monitoring report\nreport = {\n    \"timestamp\": __import__(\"datetime\").datetime.now().isoformat(),\n    \"cpu_usage\": cpu_percent,\n    \"memory_usage\": memory.percent,\n    \"disk_usage\": disk.percent,\n    \"status\": \"healthy\" if cpu_percent < 80 and memory.percent < 80 else \"warning\"\n}\n\nprint(json.dumps(report, indent=2))",
    "requirements": ["psutil"],
    "environmentVariables": {
      "MONITORING_ENABLED": "true"
    },
    "isActive": true,
    "timeout": 300000,
    "maxRetries": 1
  }'

Advanced Job Examples

Job with Complex Dependencies

# Create a job that uses multiple Python packages
curl -X POST http://localhost:3000/api/jobs \
  -H "Authorization: Bearer $JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Data Analysis Job",
    "description": "Analyze data using pandas and numpy",
    "cronPattern": "0 2 * * *",
    "pythonScript": "import pandas as pd\nimport numpy as np\nimport json\n\n# Generate sample data\ndata = {\n    \"values\": np.random.normal(100, 15, 1000).tolist(),\n    \"categories\": np.random.choice([\"A\", \"B\", \"C\"], 1000).tolist()\n}\n\ndf = pd.DataFrame(data)\n\n# Perform analysis\nanalysis = {\n    \"mean\": float(df[\"values\"].mean()),\n    \"std\": float(df[\"values\"].std()),\n    \"count_by_category\": df[\"categories\"].value_counts().to_dict(),\n    \"timestamp\": __import__(\"datetime\").datetime.now().isoformat()\n}\n\nprint(json.dumps(analysis, indent=2))",
    "requirements": ["pandas", "numpy"],
    "environmentVariables": {
      "ANALYSIS_TYPE": "statistical",
      "SAMPLE_SIZE": "1000"
    },
    "isActive": true,
    "timeout": 600000,
    "maxRetries": 2
  }'

Job with Error Handling

# Create a job with robust error handling
curl -X POST http://localhost:3000/api/jobs \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Robust API Job",
    "description": "Job with comprehensive error handling",
    "cronPattern": "0 */6 * * *",
    "pythonScript": "import requests\nimport json\nimport sys\n\ntry:\n    # Attempt to fetch data\n    response = requests.get(\"https://api.example.com/data\", timeout=30)\n    response.raise_for_status()\n    \n    data = response.json()\n    \n    # Process data\n    result = {\n        \"status\": \"success\",\n        \"data_count\": len(data) if isinstance(data, list) else 1,\n        \"timestamp\": __import__(\"datetime\").datetime.now().isoformat()\n    }\n    \n    print(json.dumps(result, indent=2))\n    \nexcept requests.exceptions.RequestException as e:\n    print(f\"Request failed: {e}\", file=sys.stderr)\n    sys.exit(1)\n    \nexcept json.JSONDecodeError as e:\n    print(f\"JSON decode error: {e}\", file=sys.stderr)\n    sys.exit(1)\n    \nexcept Exception as e:\n    print(f\"Unexpected error: {e}\", file=sys.stderr)\n    sys.exit(1)",
    "requirements": ["requests"],
    "environmentVariables": {
      "API_TIMEOUT": "30",
      "RETRY_COUNT": "3"
    },
    "isActive": true,
    "timeout": 300000,
    "maxRetries": 3
  }'

Managing Jobs

List All Jobs

# List jobs (public endpoint - no authentication required)
curl http://localhost:3000/api/jobs

# List jobs with pagination
curl "http://localhost:3000/api/jobs?page=1&limit=10"

# List jobs with authentication for additional details
curl -H "Authorization: Bearer $JWT_TOKEN" http://localhost:3000/api/jobs

Get Job Details

# Get basic job details (public - filtered data)
curl http://localhost:3000/api/jobs/68ca6ea99ad4c9a6fa530bee

# Get complete job details including sensitive info (requires authentication)
curl -H "Authorization: Bearer $JWT_TOKEN" \
  http://localhost:3000/api/jobs/68ca6ea99ad4c9a6fa530bee/details

# Using API key
curl -H "X-API-Key: $API_KEY" \
  http://localhost:3000/api/jobs/68ca6ea99ad4c9a6fa530bee/details

Get Individual Job Components

# Get only the Python script
curl -H "Authorization: Bearer $JWT_TOKEN" \
  http://localhost:3000/api/jobs/68ca6ea99ad4c9a6fa530bee/script

# Response:
# {
#   "jobId": "68ca6ea99ad4c9a6fa530bee",
#   "jobName": "Test Python Job",
#   "pythonScript": "print(\"Hello from PyJob!\")\nprint(\"Current time:\", __import__(\"datetime\").datetime.now())"
# }

# Get only the requirements
curl -H "Authorization: Bearer $JWT_TOKEN" \
  http://localhost:3000/api/jobs/68ca6ea99ad4c9a6fa530bee/requirements

# Response:
# {
#   "jobId": "68ca6ea99ad4c9a6fa530bee",
#   "jobName": "Test Python Job",
#   "requirements": ["requests"]
# }

# Get only the environment variables
curl -H "Authorization: Bearer $JWT_TOKEN" \
  http://localhost:3000/api/jobs/68ca6ea99ad4c9a6fa530bee/env

# Response:
# {
#   "jobId": "68ca6ea99ad4c9a6fa530bee",
#   "jobName": "Test Python Job",
#   "environmentVariables": {
#     "TEST_VAR": "test_value"
#   }
# }

Update Job

# Update job configuration
curl -X PUT http://localhost:3000/api/jobs/68ca6ea99ad4c9a6fa530bee \
  -H "Authorization: Bearer $JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Updated Job Name",
    "description": "Updated description",
    "cronPattern": "0 */2 * * *",
    "isActive": true
  }'

Toggle Job Status

# Enable/disable a job
curl -X PATCH http://localhost:3000/api/jobs/68ca6ea99ad4c9a6fa530bee/toggle \
  -H "Authorization: Bearer $JWT_TOKEN"

# Using API key
curl -X PATCH http://localhost:3000/api/jobs/68ca6ea99ad4c9a6fa530bee/toggle \
  -H "X-API-Key: $API_KEY"

Executing Jobs

Manual Job Execution

# Execute job manually (JWT Token)
curl -X POST http://localhost:3000/api/jobs/68ca6ea99ad4c9a6fa530bee/execute \
  -H "Authorization: Bearer $JWT_TOKEN"

# Execute job manually (API Key)
curl -X POST http://localhost:3000/api/jobs/68ca6ea99ad4c9a6fa530bee/execute \
  -H "X-API-Key: $API_KEY"

# Execute job manually (Basic Auth)
curl -X POST http://localhost:3000/api/jobs/68ca6ea99ad4c9a6fa530bee/execute \
  -H "Authorization: Basic $(echo -n 'john_doe:securepassword123' | base64)"

View Job Execution History

# Get execution history
curl -H "Authorization: Bearer $JWT_TOKEN" \
  http://localhost:3000/api/jobs/68ca6ea99ad4c9a6fa530bee/executions

# Response:
# {
#   "executions": [
#     {
#       "_id": "68ca6ebb9ad4c9a6fa530bf8",
#       "jobId": "68ca6ea99ad4c9a6fa530bee",
#       "jobName": "Test Python Job",
#       "status": "completed",
#       "retryCount": 0,
#       "triggeredBy": "manual",
#       "startedAt": "2025-09-17T08:18:03.836Z",
#       "completedAt": "2025-09-17T08:18:09.059Z",
#       "duration": 5223,
#       "exitCode": 0,
#       "stderr": "",
#       "stdout": "Hello from PyJob!\nCurrent time: 2025-09-17 10:18:09.057612"
#     }
#   ],
#   "pagination": {
#     "page": 1,
#     "limit": 10,
#     "total": 1,
#     "pages": 1
#   }
# }

View Job Logs

# Get job logs
curl -H "Authorization: Bearer $JWT_TOKEN" \
  http://localhost:3000/api/jobs/68ca6ea99ad4c9a6fa530bee/logs

Deleting Jobs

Delete Job

# Delete a job (JWT Token)
curl -X DELETE http://localhost:3000/api/jobs/68ca6ea99ad4c9a6fa530bee \
  -H "Authorization: Bearer $JWT_TOKEN"

# Delete a job (API Key)
curl -X DELETE http://localhost:3000/api/jobs/68ca6ea99ad4c9a6fa530bee \
  -H "X-API-Key: $API_KEY"

# Delete a job (Basic Auth)
curl -X DELETE http://localhost:3000/api/jobs/68ca6ea99ad4c9a6fa530bee \
  -H "Authorization: Basic $(echo -n 'john_doe:securepassword123' | base64)"

Search and Statistics

Search Jobs

# Search jobs by name or description
curl "http://localhost:3000/api/jobs/search?q=python"

# Search with filters
curl "http://localhost:3000/api/jobs/search?q=data&status=active&page=1&limit=5"

Get Statistics

# Get job statistics
curl http://localhost:3000/api/jobs/stats/overview

# Response:
# {
#   "totalJobs": 5,
#   "activeJobs": 3,
#   "inactiveJobs": 2,
#   "totalExecutions": 150,
#   "successfulExecutions": 145,
#   "failedExecutions": 5,
#   "averageExecutionTime": 2500,
#   "lastExecution": "2025-09-17T08:15:30.000Z"
# }

Get Scheduled Jobs Status

# Get scheduled jobs status (requires authentication)
curl -H "Authorization: Bearer $JWT_TOKEN" \
  http://localhost:3000/api/jobs/scheduled/status

Admin Functions

Export Jobs Data (Admin Only)

# Export all jobs data
curl -H "Authorization: Bearer $ADMIN_JWT_TOKEN" \
  http://localhost:3000/api/jobs/export

# Export with filters
curl -H "Authorization: Bearer $ADMIN_JWT_TOKEN" \
  "http://localhost:3000/api/jobs/export?format=json&includeExecutions=true"

System Health Check

# Basic health check (public)
curl http://localhost:3000/health

# Detailed system health (public)
curl http://localhost:3000/api/jobs/health/status

# Response:
# {
#   "status": "healthy",
#   "timestamp": "2025-09-17T08:15:30.000Z",
#   "scheduler": {
#     "isRunning": true,
#     "scheduledJobs": 3
#   },
#   "environments": {
#     "active": 0,
#     "maxConcurrent": 5
#   },
#   "database": {
#     "connected": true
#   },
#   "redis": {
#     "enabled": false,
#     "connected": false,
#     "available": false
#   },
#   "cache": {
#     "redisAvailable": false,
#     "totalCachedResults": 0,
#     "totalCachedConfigs": 0
#   }
# }

πŸ”§ CRON Pattern Reference

Basic CRON Format

* * * * *
β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ β”‚ β”‚ β”‚ └─── Day of week (0-6, Sunday = 0)
β”‚ β”‚ β”‚ └───── Month (1-12)
β”‚ β”‚ └─────── Day of month (1-31)
β”‚ └───────── Hour (0-23)
└─────────── Minute (0-59)

Common Patterns

Pattern Description Example
*/5 * * * * Every 5 minutes 0, 5, 10, 15, 20...
0 * * * * Every hour At minute 0 of every hour
0 */2 * * * Every 2 hours At minute 0 of every 2nd hour
0 9 * * * Daily at 9 AM Every day at 09:00
0 9 * * 1-5 Weekdays at 9 AM Monday to Friday at 09:00
0 0 * * 0 Weekly on Sunday Every Sunday at midnight
0 0 1 * * Monthly First day of every month at midnight
0 0 1 1 * Yearly January 1st at midnight

Advanced Patterns

Pattern Description
15,45 * * * * At 15 and 45 minutes past every hour
0 9-17 * * 1-5 Every hour from 9 AM to 5 PM, Monday to Friday
0 0 */3 * * Every 3 days at midnight
0 0 1,15 * * 1st and 15th of every month at midnight

πŸ›‘οΈ Security Best Practices

Authentication Security

  1. Use Strong Passwords: Minimum 8 characters with mixed case, numbers, and symbols
  2. Rotate API Keys: Regularly generate new API keys and revoke old ones
  3. Use HTTPS: Always use HTTPS in production environments
  4. Token Expiration: JWT tokens expire after 24 hours by default
  5. Role-based Access: Use appropriate roles (admin/user) for different access levels

Job Security

  1. Environment Variables: Store sensitive data in environment variables, not in the script
  2. Timeout Limits: Set appropriate timeout values to prevent runaway jobs
  3. Resource Limits: Configure maximum concurrent jobs to prevent resource exhaustion
  4. Input Validation: Validate all job inputs and parameters
  5. Error Handling: Implement proper error handling in your Python scripts

Example Secure Job

curl -X POST http://localhost:3000/api/jobs \
  -H "Authorization: Bearer $JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Secure Data Job",
    "description": "Secure job with proper error handling",
    "cronPattern": "0 */6 * * *",
    "pythonScript": "import os\nimport sys\nimport json\n\ntry:\n    # Use environment variables for sensitive data\n    api_key = os.getenv(\"API_KEY\")\n    if not api_key:\n        print(\"Error: API_KEY not found\", file=sys.stderr)\n        sys.exit(1)\n    \n    # Your secure logic here\n    result = {\"status\": \"success\", \"timestamp\": __import__(\"datetime\").datetime.now().isoformat()}\n    print(json.dumps(result))\n    \nexcept Exception as e:\n    print(f\"Error: {e}\", file=sys.stderr)\n    sys.exit(1)",
    "requirements": [],
    "environmentVariables": {
      "API_KEY": "your-secret-api-key-here"
    },
    "isActive": true,
    "timeout": 300000,
    "maxRetries": 2
  }'

🚨 Troubleshooting

Common Issues

Authentication Errors

# Check if user exists
curl -H "Authorization: Bearer $JWT_TOKEN" http://localhost:3000/api/auth/me

# If token is expired, login again
curl -X POST http://localhost:3000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"your_username","password":"your_password"}'

Job Execution Issues

# Check job execution history
curl -H "Authorization: Bearer $JWT_TOKEN" \
  http://localhost:3000/api/jobs/JOB_ID/executions

# Check job logs
curl -H "Authorization: Bearer $JWT_TOKEN" \
  http://localhost:3000/api/jobs/JOB_ID/logs

System Health

# Check system health
curl http://localhost:3000/api/jobs/health/status

# Check if MongoDB is connected
curl http://localhost:3000/health

Error Codes

Code Description Solution
401 Unauthorized Check authentication credentials
403 Forbidden Check user permissions/role
404 Not Found Verify job ID or endpoint
400 Bad Request Check request format and validation
500 Internal Error Check server logs and system health

πŸ“Š Monitoring and Logging

Log Files

Logs are stored in the logs/ directory:

  • combined.log - All application logs
  • error.log - Error logs only

Monitoring Endpoints

# System health
curl http://localhost:3000/api/jobs/health/status

# Job statistics
curl http://localhost:3000/api/jobs/stats/overview

# Scheduled jobs status
curl -H "Authorization: Bearer $JWT_TOKEN" \
  http://localhost:3000/api/jobs/scheduled/status

This comprehensive guide covers all aspects of using PyJob effectively. Whether you're a developer integrating with the API or an administrator managing the system, these examples will help you get the most out of PyJob's powerful job scheduling capabilities.

Security Features

  • Isolated Execution: Each job runs in its own virtual environment
  • Restricted File Access: Python scripts cannot write to the local file system
  • Environment Variables: Secure handling of sensitive data
  • Timeout Protection: Jobs are automatically terminated if they exceed the timeout
  • Resource Limits: Configurable limits on concurrent job executions
  • Authentication: Multiple auth methods (JWT, API keys, Basic Auth)
  • Rate Limiting: Protection against abuse and brute force attacks
  • Role-based Access: Admin and user roles with different permissions
  • Secure Password Storage: Bcrypt hashing for user passwords

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   REST API      β”‚    β”‚  Job Scheduler   β”‚    β”‚ Virtual Env     β”‚
β”‚   (Express)     │◄──►│  (node-cron)     │◄──►│ Manager         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                       β”‚                       β”‚
         β–Ό                       β–Ό                       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   MongoDB       β”‚    β”‚  Job Execution   β”‚    β”‚ Python Scripts  β”‚
β”‚   (NoSQL)       β”‚    β”‚  Tracking        β”‚    β”‚ (Isolated)      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Development

Running Tests

npm test

Development Mode

npm run dev

Logs

Logs are stored in the logs/ directory:

  • combined.log - All logs
  • error.log - Error logs only

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests if applicable
  5. Submit a pull request

License

MIT License - see LICENSE file for details.

About

Scheduler for Python Jobs with REDIS integration and MongoDB Backend written in node.js with express REST API

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages