
# Пакетна обработка

Пакетите ви позволяват да изпратите група задания и да ги проследявате като едно цяло. Можете да регистрирате функции за обратно извикване, които се задействат при успешно приключване на пакета, при неуспешно задание или при приключване на пакета независимо от резултата. Queuety автоматично проследява напредъка, неуспехите и състоянието на отмяната.

## Създаване на пакет

Използвайте `Queuety::create_batch()`, за да стартирате `BatchBuilder`. Подайте масив от екземпляри на `Contracts\Job`, след което извикайте `dispatch()`, за да създадете реда на пакета и всички задания.

```php
use Queuety\Queuety;

$batch = Queuety::create_batch( [
    new ImportUsersJob( $csv_chunk_1 ),
    new ImportUsersJob( $csv_chunk_2 ),
    new ImportUsersJob( $csv_chunk_3 ),
] )
    ->name( 'Import users' )
    ->on_queue( 'imports' )
    ->dispatch();

echo $batch->id; // The batch ID
```

`dispatch()` връща стойностен обект `Batch` със състоянието на пакета.

Можете също да подадете масиви с обработваща функция и полезен товар вместо екземпляри на задания:

```php
$batch = Queuety::create_batch( [
    [ 'handler' => 'import_users', 'payload' => [ 'chunk' => 1 ] ],
    [ 'handler' => 'import_users', 'payload' => [ 'chunk' => 2 ] ],
] )->dispatch();
```

## Функции за обратно извикване

Регистрирайте класове на обработващи функции, които да се извикват в различни моменти от жизнения цикъл на пакета. Всеки клас на обработваща функция трябва да има метод `handle( Batch $batch )`.

```php
$batch = Queuety::create_batch( $jobs )
    ->name( 'Import users' )
    ->then( ImportCompleteHandler::class )
    ->catch( ImportFailedHandler::class )
    ->finally( ImportCleanupHandler::class )
    ->dispatch();
```

| Метод | Кога се задейства |
|---|---|
| `then( $handler_class )` | Всички задания са завършили успешно (или е зададено `allow_failures()`) |
| `catch( $handler_class )` | Първото задание в пакета е неуспешно |
| `finally( $handler_class )` | Пакетът приключва, независимо дали е завършил успешно или не |

### Писане на обработваща функция за обратно извикване

```php
use Queuety\Batch;

class ImportCompleteHandler {
    public function handle( Batch $batch ): void {
        // All users imported. Send a notification.
        error_log( "Batch {$batch->id} completed: {$batch->total_jobs} jobs processed." );
    }
}

class ImportFailedHandler {
    public function handle( Batch $batch ): void {
        error_log( "Batch {$batch->id} had a failure. Failed jobs: {$batch->failed_jobs}" );
    }
}

class ImportCleanupHandler {
    public function handle( Batch $batch ): void {
        // Runs regardless of outcome. Clean up temp files, etc.
    }
}
```

## Допускане на неуспехи

По подразбиране функцията за обратно извикване `then` се задейства само ако всички задания в пакета са успешни. Извикайте `allow_failures()`, за да позволите задействането на функцията за обратно извикване `then` дори когато някои задания са неуспешни.

```php
$batch = Queuety::create_batch( $jobs )
    ->then( ReportHandler::class )
    ->allow_failures()
    ->dispatch();
```

## Проследяване на напредъка

Обектът със стойности `Batch` предоставя свойства и методи за проследяване на напредъка.

```php
$batch = Queuety::find_batch( $batch_id );

$batch->progress();      // 0-100 percentage
$batch->finished();      // true if all jobs are done
$batch->has_failures();  // true if any job failed
$batch->cancelled();     // true if the batch was cancelled

$batch->total_jobs;      // Total number of jobs
$batch->pending_jobs;    // Jobs still pending
$batch->failed_jobs;     // Number of failed jobs
$batch->failed_job_ids;  // Array of failed job IDs
```

| Метод/свойство | Тип | Описание |
|---|---|---|
| `progress()` | `int` | Процент на завършване от 0 до 100 |
| `finished()` | `bool` | Дали пакетът е приключил (всички задачи са завършени или са неуспешни) |
| `has_failures()` | `bool` | Дали някоя задача в пакета е неуспешна |
| `cancelled()` | `bool` | Дали пакетът е отменен |
| `$total_jobs` | `int` | Общ брой задачи в пакета |
| `$pending_jobs` | `int` | Брой задачи, които все още чакат |
| `$failed_jobs` | `int` | Брой неуспешни задачи |
| `$failed_job_ids` | `array` | Идентификатори на неуспешните задачи |
| `$name` | `string\|null` | Незадължително име на пакета |
| `$created_at` | `DateTimeImmutable` | Кога е създаден пакетът |
| `$finished_at` | `DateTimeImmutable\|null` | Кога пакетът е приключил |
| `$cancelled_at` | `DateTimeImmutable\|null` | Кога пакетът е отменен |

## Отмяна

Отменете пакет чрез `BatchManager`. Отмяната на пакет задава `cancelled_at` и `finished_at` и задейства обратното извикване `finally`.

```php
Queuety::batch_manager()->cancel( $batch_id );
```

Отмяната маркира пакета като отменен и приключил и задейства обратното извикване `finally`. Тя не засяга задачите: чакащите задачи в отменен пакет продължават да се изпълняват, но резултатите им вече не актуализират броячите на пакета и не задействат `then`, `catch` или `finally`. Изтрийте задачите сами, ако не трябва да се изпълняват.

## Намиране на пакети

Потърсете пакет по неговия идентификатор:

```php
$batch = Queuety::find_batch( $batch_id );

if ( null === $batch ) {
    // Batch not found.
}
```

## Премахване на стари пакети

Премахнете приключилите пакети, които са по-стари от зададен брой дни:

```php
$deleted = Queuety::batch_manager()->prune( 30 ); // Delete batches finished > 30 days ago
```

Изтриват се само пакети с ненулев времеви печат `finished_at`. Активните пакети никога не се премахват автоматично.
