# Cronjob Execution Flow

## Overview

This document describes the detailed execution flow of cronjobs in the system, from OS-level scheduling to completion tracking.

## High-Level Flow

```
┌─────────────────┐
│  OS Cronjob     │  (crontab entry)
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  Entry Point    │  (PHP script called by cron)
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  Cron::method() │  (Specific cronjob method)
└────────┬────────┘
         │
         ├─────────────────────────────────────┐
         │                                     │
         ▼                                     ▼
┌─────────────────┐                  ┌─────────────────┐
│  Validation     │                  │  Check Status   │
│  - Date format  │                  │  - Already ran? │
│  - Parameters   │                  │  - Success?     │
└────────┬────────┘                  └────────┬────────┘
         │                                     │
         └─────────────────┬─────────────────┘
                           │
                           ▼
                  ┌─────────────────┐
                  │  Record Start   │  (_record_cron)
                  │  - Create DB    │
                  │    record       │
                  │  - Set status  │
                  │    to running   │
                  └────────┬────────┘
                           │
                           ▼
                  ┌─────────────────┐
                  │  Execute Logic   │
                  │  - Business      │
                  │    operations    │
                  └────────┬────────┘
                           │
         ┌─────────────────┴─────────────────┐
         │                                   │
         ▼                                   ▼
┌─────────────────┐                  ┌─────────────────┐
│  Success Path   │                  │  Error Path     │
│  - Set success  │                  │  - Set error    │
│  - Collect msg  │                  │  - Log details  │
└────────┬────────┘                  └────────┬────────┘
         │                                   │
         └─────────────────┬─────────────────┘
                           │
                           ▼
                  ┌─────────────────┐
                  │  Update Record  │  (_update_complete_cron)
                  │  - Set completed│
                  │  - Set success  │
                  │  - Set message  │
                  │  - Set end time │
                  └────────┬────────┘
                           │
                           ▼
                  ┌─────────────────┐
                  │  Log Results     │
                  │  - Critical errs │
                  │  - Transaction   │
                  └──────────────────┘
```

## Detailed Step-by-Step Flow

### Step 1: OS Cronjob Trigger

**Location**: System crontab (e.g., `/etc/crontab`)

**Example Entry**:
```bash
0 1 * * * /usr/bin/php /path/to/cron_script.php send_brith_noti 2024-01-15
```

**What Happens**:
- OS cron daemon executes the command at scheduled time
- PHP script receives arguments (method name, date)

### Step 2: Entry Point Initialization

**Location**: PHP script entry point

**What Happens**:
- Parse command-line arguments
- Load required classes and dependencies
- Call appropriate `Cron::method()` with parameters

### Step 3: Method Initialization

**Location**: `Cron::method()` (e.g., `send_brith_noti()`)

**Code Flow**:
```php
static::_initialize();  // Ensure system is ready
$method_code = 'A111';   // Set method identifier
$actionCode = static::$_class_code . $method_code;  // '0801A111'
$transCode = static::$_class_trans_code . 'send-brith-noti';  // 'cron-send-brith-noti'
```

**What Happens**:
- Initialize database connection (if not already done)
- Set current datetime
- Create singleton instance
- Set up error tracking codes

### Step 4: Error Reset

**Code Flow**:
```php
static::_reset_errors();
```

**What Happens**:
- Clear previous error codes
- Clear previous log messages
- Prepare fresh error tracking

### Step 5: Input Validation

**Code Flow**:
```php
static::validate_cron_date($date);
```

**What Happens**:
- Validate date format (must be YYYY-MM-DD)
- Throw exception if invalid
- Set error code `A410001` on failure

### Step 6: Duplicate Check (Optional)

**Code Flow**:
```php
if (!static::is_cron_ran($cron_code, $date)) {
    // Continue execution
}
```

**What Happens**:
- Query database for existing record with same code and date
- Return early if already executed
- **Note**: Some methods skip this check

**Variations**:
- `is_cron_ran()`: Check if any execution exists
- `is_cron_ran_success()`: Check if successful execution exists (allows rerun on failure)

### Step 7: Record Cron Start

**Code Flow**:
```php
try {
    $cron_id = static::_record_cron($cron_code, $date);
} catch (exception $e) {
    // Log critical error and exit
    $error = true;
}
```

**What Happens**:
- Insert new record into `cron` table
- Set initial status:
  - `completed`: 'n'
  - `success`: 'n'
  - `started`: current datetime
- Extract year, month, day from date
- Store `odate` (YYYY-MM-DD format)
- Return `cron_id` for later update

**Database Record**:
```sql
INSERT INTO cron (code, started, completed, success, year, month, day, odate)
VALUES ('A111', '2024-01-15 01:00:00', 'n', 'n', 2024, 1, 15, '2024-01-15')
```

### Step 8: Execute Business Logic

**Code Flow**:
```php
if (!$error) {
    try {
        $user = new User();
        $result = $user->insert_today_birth($date);
    } catch (exception $e) {
        static::_set_error_code($method_code . '001');
        $log = $e->getCode() . ': ' . $e->getMessage() . "\n" . Util::format_trace($e->getTrace());
        static::_set_log($log);
        $exec_error = true;
    }
}
```

**What Happens**:
- Execute actual business logic
- Catch any exceptions
- Set error code and log on exception
- Set `$exec_error` flag

**Error Handling**:
- Error code format: `{method_code}001` (e.g., `A111001`)
- Log includes exception code, message, and stack trace

### Step 9: Determine Success/Failure

**Code Flow**:
```php
$message = '';
$success = true;
if ($result['error']) {
    $message = Util::format_array_to_text($result);
    $success = false;
}
if ($exec_error) {
    $message .= ($message ? "\n" : '') . static::$logs;
    $success = false;
}
```

**What Happens**:
- Check if business logic returned error
- Check if execution exception occurred
- Combine error messages
- Set `$success` flag accordingly

### Step 10: Update Cron Record

**Code Flow**:
```php
try {
    static::_update_complete_cron($cron_id, $success, $message);
} catch (exception $e) {
    // Log critical error
}
```

**What Happens**:
- Update the cron record with completion status
- Set fields:
  - `completed`: 'y'
  - `success`: 'y' or 'n'
  - `ended`: current datetime
  - `message`: success/error message
  - `err_code`: error code (if any)

**Database Update**:
```sql
UPDATE cron 
SET completed = 'y', 
    success = 'y', 
    ended = '2024-01-15 01:00:05',
    message = '',
    err_code = ''
WHERE id = 12345
```

### Step 11: Logging (Error Cases)

**Code Flow**:
```php
catch (exception $e) {
    $log = "Error recording cron in " . __METHOD__ . ".\n\n" . $e->getMessage();
    Log::logCriticalErrors($actionCode, $transCode, $log);
}
```

**What Happens**:
- Log critical errors to system log
- Include action code and transaction code for tracing
- Used for database operation failures

## Special Execution Patterns

### Pattern 1: Always Execute

**Methods**: `update_4d_win_number()`, `get_4d_bet_details()`, `cancel_expired_speedpay_payment()`, etc.

**Flow**:
- Skip duplicate check
- Always record and execute
- Useful for operations that can run multiple times safely

### Pattern 2: Rerun on Failure

**Methods**: `login_user_update_game_wallet()`, `distribute_comm()`

**Flow**:
- Use `is_cron_ran_success()` instead of `is_cron_ran()`
- Only skip if previous execution was successful
- Allows automatic retry on failure

### Pattern 3: Rate Limited Execution

**Methods**: `get_game_bet_details()`

**Flow**:
- Use system key locking to prevent concurrent execution
- Process in batches with iteration and time limits
- Release lock when done

**Example**:
```php
$bet_cron_running = System::get_value('bet_cron_running');
if (!$bet_cron_running) {
    System::set_value('bet_cron_running', 1);
    // Process batches
    while ($count < LIMIT && $runtime <= TIME_LIMIT) {
        // Process batch
    }
    System::set_value('bet_cron_running', 0);
}
```

### Pattern 4: Weekly Distribution

**Methods**: `distribute_comm()` (for turnover-bonus)

**Flow**:
- Check if today is Monday
- Calculate previous week range (Monday to Sunday)
- Loop through each day in the week
- Distribute commission for each day

## Error Scenarios

### Scenario 1: Database Record Failure

**When**: `_record_cron()` throws exception

**Handling**:
- Log critical error
- Set `$error = true`
- Skip business logic execution
- Exit method

### Scenario 2: Business Logic Exception

**When**: Business logic throws exception

**Handling**:
- Catch exception
- Set error code
- Log error details
- Set `$exec_error = true`
- Continue to update step (mark as failed)

### Scenario 3: Update Record Failure

**When**: `_update_complete_cron()` throws exception

**Handling**:
- Log critical error
- Record remains in "running" state
- May need manual intervention

## State Transitions

### Cron Record States

```
[Not Started]
    │
    ▼
[Recorded] ── completed: 'n', success: 'n'
    │
    ├─── [Executing Business Logic]
    │
    ├─── [Success] ── completed: 'y', success: 'y'
    │
    └─── [Failed] ── completed: 'y', success: 'n', err_code: '...'
```

## Best Practices

1. **Always validate input** before processing
2. **Check execution status** to prevent duplicates (unless intentional)
3. **Wrap business logic** in try-catch blocks
4. **Set appropriate error codes** for debugging
5. **Log critical errors** for monitoring
6. **Update completion status** even on failure
7. **Use transaction codes** for log correlation
