Fix code quality violations and enhance ROUTE-EXISTS-01 rule

Implement JQHTML function cache ID system and fix bundle compilation
Implement underscore prefix for system tables
Fix JS syntax linter to support decorators and grant exception to Task system
SPA: Update planning docs and wishlists with remaining features
SPA: Document Navigation API abandonment and future enhancements
Implement SPA browser integration with History API (Phase 1)
Convert contacts view page to SPA action
Convert clients pages to SPA actions and document conversion procedure
SPA: Merge GET parameters and update documentation
Implement SPA route URL generation in JavaScript and PHP
Implement SPA bootstrap controller architecture
Add SPA routing manual page (rsx:man spa)
Add SPA routing documentation to CLAUDE.md
Phase 4 Complete: Client-side SPA routing implementation
Update get_routes() consumers for unified route structure
Complete SPA Phase 3: PHP-side route type detection and is_spa flag
Restore unified routes structure and Manifest_Query class
Refactor route indexing and add SPA infrastructure
Phase 3 Complete: SPA route registration in manifest
Implement SPA Phase 2: Extract router code and test decorators
Rename Jqhtml_Component to Component and complete SPA foundation setup

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-11-19 17:48:15 +00:00
parent 77b4d10af8
commit 9ebcc359ae
4360 changed files with 37751 additions and 18578 deletions

295
app/RSpade/Core/Task/CLAUDE.md Executable file
View File

@@ -0,0 +1,295 @@
# Task System
RSpade provides a unified task execution system supporting immediate CLI execution, queued async tasks, and scheduled cron-based tasks.
## Creating Task Services
Task services must extend `Rsx_Service_Abstract` and use attributes to define tasks:
```php
use App\RSpade\Core\Service\Rsx_Service_Abstract;
use App\RSpade\Core\Task\Task_Instance;
class My_Service extends Rsx_Service_Abstract
{
// Simple task (can be run via CLI or dispatched to queue)
#[Task('Description of what this task does')]
public static function my_task(Task_Instance $task, array $params = [])
{
$task->info('Task is running');
// Task logic here
return ['result' => 'success'];
}
// Scheduled task (runs automatically via cron)
#[Task('Cleanup old records')]
#[Schedule('0 2 * * *')] // Daily at 2 AM
public static function cleanup(Task_Instance $task, array $params = [])
{
$task->info('Cleanup running');
// Cleanup logic here
}
}
```
## Requirements
- Class MUST extend `Rsx_Service_Abstract`
- Method MUST be `public static`
- Method MUST have signature: `(Task_Instance $task, array $params = [])`
- Method MUST have `#[Task('description')]` attribute
- Scheduled tasks also need `#[Schedule('cron_expression')]` attribute
## Important Notes on Attributes
- Attributes work via reflection - NO backing PHP classes needed
- The linter will remove `use` statements for attributes - this is INTENTIONAL and CORRECT
- Use `#[Task]` and `#[Schedule]`, NOT `#[Task_Attribute]` or any other variation
- Never create PHP classes for these attributes
## Task_Instance Methods
The `$task` parameter provides logging and progress tracking:
```php
public static function process_items(Task_Instance $task, array $params = [])
{
$items = Item_Model::all();
$total = count($items);
$task->info("Processing {$total} items");
foreach ($items as $index => $item) {
// Update progress
$task->progress($index + 1, $total);
// Log info
$task->info("Processing item {$item->id}");
// Log warnings
if ($item->status === 'pending') {
$task->warning("Item {$item->id} is still pending");
}
// Process item
$item->process();
}
$task->info("Completed processing {$total} items");
return ['processed' => $total];
}
```
## Running Tasks
### CLI Execution
```bash
# List all available tasks
php artisan rsx:task:list
# Run task immediately from CLI (synchronous)
php artisan rsx:task:run Service_Class method_name
# Run with parameters
php artisan rsx:task:run Service_Class method_name '{"param":"value"}'
```
### Programmatic Dispatch
```php
// Dispatch task to queue (async)
use App\RSpade\Core\Task\Task;
Task::dispatch('Service_Class', 'method_name', ['param' => 'value']);
// Dispatch with delay
Task::dispatch('Service_Class', 'method_name', ['param' => 'value'], 60); // 60 second delay
```
### Scheduled Execution
Tasks with `#[Schedule]` attribute run automatically via cron.
Add to crontab:
```cron
* * * * * cd /var/www/html && php artisan rsx:task:process
```
This runs every minute and:
1. Processes any queued tasks
2. Runs scheduled tasks that are due
## Cron Expression Syntax
```
┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of month (1 - 31)
│ │ │ ┌───────────── month (1 - 12)
│ │ │ │ ┌───────────── day of week (0 - 6) (Sunday to Saturday)
│ │ │ │ │
│ │ │ │ │
* * * * *
```
Common patterns:
- `*/5 * * * *` - Every 5 minutes
- `*/30 * * * *` - Every 30 minutes
- `0 * * * *` - Every hour
- `0 2 * * *` - Daily at 2 AM
- `0 */6 * * *` - Every 6 hours
- `0 0 * * 0` - Weekly on Sunday at midnight
- `0 0 1 * *` - Monthly on the 1st at midnight
- `30 2 * * 1-5` - Weekdays at 2:30 AM
## Task Queue
Tasks dispatched via `Task::dispatch()` are stored in the database queue:
```sql
task_queue
├── id (bigint)
├── service_class (varchar)
├── method_name (varchar)
├── parameters (json)
├── status (enum: pending, processing, completed, failed)
├── attempts (int)
├── run_at (timestamp)
├── started_at (timestamp)
├── completed_at (timestamp)
├── error_message (text)
└── timestamps
```
## Error Handling
Tasks that throw exceptions:
1. Are marked as `failed` in the queue
2. Error message is logged
3. Can be retried manually via CLI
4. Maximum 3 automatic retry attempts
```php
public static function risky_task(Task_Instance $task, array $params = [])
{
try {
// Risky operation
$result = External_API::call();
} catch (Exception $e) {
$task->error("API call failed: " . $e->getMessage());
throw $e; // Re-throw to mark task as failed
}
return $result;
}
```
## Best Practices
1. **Keep tasks idempotent** - Safe to run multiple times
2. **Log progress** for long-running tasks
3. **Return meaningful data** for debugging
4. **Use transactions** for database operations
5. **Set appropriate schedules** to avoid overlap
6. **Handle exceptions gracefully**
7. **Keep tasks focused** - one task, one purpose
## Common Task Patterns
### Cleanup Task
```php
#[Task('Clean old logs')]
#[Schedule('0 3 * * *')] // Daily at 3 AM
public static function cleanup_logs(Task_Instance $task, array $params = [])
{
$cutoff = now()->subDays(30);
$deleted = Log_Model::where('created_at', '<', $cutoff)->delete();
$task->info("Deleted {$deleted} old log entries");
return ['deleted' => $deleted];
}
```
### Import Task
```php
#[Task('Import data from CSV')]
public static function import_csv(Task_Instance $task, array $params = [])
{
$file_path = $params['file_path'] ?? null;
if (!$file_path || !file_exists($file_path)) {
throw new Exception("File not found: {$file_path}");
}
$handle = fopen($file_path, 'r');
$row_count = 0;
while (($data = fgetcsv($handle)) !== false) {
$row_count++;
$task->progress($row_count);
// Process row
Model::create([
'field1' => $data[0],
'field2' => $data[1],
]);
}
fclose($handle);
$task->info("Imported {$row_count} rows");
return ['imported' => $row_count];
}
```
### Report Generation
```php
#[Task('Generate monthly report')]
#[Schedule('0 0 1 * *')] // First day of month at midnight
public static function monthly_report(Task_Instance $task, array $params = [])
{
$start = now()->subMonth()->startOfMonth();
$end = now()->subMonth()->endOfMonth();
$task->info("Generating report for {$start->format('F Y')}");
$data = Sales_Model::whereBetween('created_at', [$start, $end])
->get();
$report = Report_Generator::create($data);
$report->save(storage_path("reports/monthly-{$start->format('Y-m')}.pdf"));
$task->info("Report generated successfully");
return [
'period' => $start->format('F Y'),
'records' => count($data),
];
}
```
## Monitoring Tasks
View task history and status:
```bash
# View pending tasks
php artisan rsx:task:pending
# View failed tasks
php artisan rsx:task:failed
# Retry failed task
php artisan rsx:task:retry {task_id}
# Clear completed tasks older than 30 days
php artisan rsx:task:clear --days=30
```
## Service Discovery
The manifest system automatically discovers all services extending `Rsx_Service_Abstract` in directories configured for scanning. Ensure your service directory is included in the manifest's `scan_directories` configuration.