
# Darbinieki

Darbinieki ir ilgstoši darbojošies procesi, kas aptaujā datubāzi, meklējot gaidošus uzdevumus, tos izpilda un virza darbplūsmas uz priekšu. Komanda `wp queuety work` darbojas WP-CLI vidē, bet pati rinda tiek paņemta tieši no MySQL, izmantojot labāko pieejamo Queuety DB draiveri.

Spraudnis instalē arī noklusēto reizi minūtē palaisto WordPress cron rezerves mehānismu vidēm bez piekļuves čaulai. Šajā lapā aplūkoti atsevišķi WP-CLI darbinieki, kas ir ieteicamais izvietošanas režīms lielākai caurlaidspējai.

## Darbinieka palaišana

```bash
wp queuety work
```

Tas palaiž vienu darbinieku rindā `default`. Tas darbojas ciklā: paņem uzdevumu, izpilda to un atkārto. Kad rinda ir tukša, tas nogaida `QUEUETY_WORKER_SLEEP` sekundes (noklusējums: 1) un tad aptaujā rindu vēlreiz.

### Opcijas

| Opcija | Apraksts |
|---|---|
| `--queue=<queue>` | Apstrādājamās Queue(s); ar komatiem atdalīts saraksts nosaka prioritāšu secību (noklusējums: `default`) |
| `--once` | Apstrādāt ne vairāk kā vienu uzdevumu un iziet |
| `--workers=<n>` | Izveidot N darbinieku procesus (nepieciešami paplašinājumi `pcntl` un `posix`) |
| `--min-workers=<n>` | Minimālais darbinieku skaits adaptīvam kopumam. Nepieciešams `--max-workers` |
| `--max-workers=<n>` | Maksimālais darbinieku skaits adaptīvam kopumam |

```bash
# Process a specific queue
wp queuety work --queue=emails

# Process at most one job and exit
wp queuety work --once

# Run 4 concurrent workers
wp queuety work --workers=4

# Scale between 2 and 6 workers as backlog changes
wp queuety work --queue=providers --min-workers=2 --max-workers=6
```

## Vairāku rindu prioritātes

Viens darbinieks var apstrādāt vairākas rindas prioritāšu secībā. Padodiet rindu nosaukumu sarakstu, kas atdalīts ar komatiem, izmantojot `--queue`:

```bash
wp queuety work --queue=critical,default,low
```

Darbinieks mēģina paņemt uzdevumu no katras rindas norādītajā secībā. Vispirms tas pārbauda `critical`. Ja `critical` ir uzdevums, tas to apstrādā. Ja `critical` ir tukša, tas pāriet pie `default` un pēc tam pie `low`. Tāpēc augstākas prioritātes rindas vienmēr tiek iztukšotas pirms zemākas prioritātes rindām.

### Kā darbojas prioritāšu secība

Katrā ciklā darbinieks mēģina paņemt uzdevumu no saraksta pirmās rindas. Ja tā ir tukša vai apturēta, darbinieks pāriet pie nākamās rindas un turpina, līdz atrod uzdevumu vai pārbauda visu sarakstu. Ja nevienā rindā uzdevums nav atrasts, darbinieks nogaida un mēģina vēlreiz. Šis ir stingrs prioritāšu modelis, tāpēc pastāvīga `critical` uzdevumu plūsma atņems resursus rindām `default` un `low`. Ja zemākas prioritātes rindām jānodrošina garantēta caurlaidspēja, izmantojiet atsevišķus darbiniekus.

### Vairāku rindu izmantošana PHP vidē

Metodes `Worker::run()` un `Worker::flush()` pieņem virkni vai masīvu:

```php
// Comma-separated string
Queuety::worker()->run( 'critical,default,low' );

// Array
Queuety::worker()->run( [ 'critical', 'default', 'low' ] );

// flush() also supports multi-queue
$count = Queuety::worker()->flush( 'critical,default,low' );
```

### Izvietošanas stratēģijas

**Atsevišķi darbinieki katrai rindai** sniedz pilnīgu kontroli pār vienlaicīgas izpildes apjomu un izolāciju. Katrai rindai ir savs darbinieka process(es), un citas rindas to nevar atstāt bez resursiem:

```ini
[program:queuety-critical]
command=wp queuety work --queue=critical
numprocs=4

[program:queuety-default]
command=wp queuety work --queue=default
numprocs=2

[program:queuety-low]
command=wp queuety work --queue=low
numprocs=1
```

**Prioritāšu secība ar vienu darbinieku** ir vienkāršāk pārvaldāma un labi darbojas, ja zemākas prioritātes rindas var pieļaut aizkavēšanos:

```ini
[program:queuety-worker]
command=wp queuety work --queue=critical,default,low
numprocs=2
```

Varat arī apvienot abas pieejas: atsevišķus darbiniekus `critical`, lai nodrošinātu caurlaidspēju, un darbinieku ar prioritāšu secību visam pārējam:

```ini
[program:queuety-critical]
command=wp queuety work --queue=critical
numprocs=2

[program:queuety-fallback]
command=wp queuety work --queue=default,low
numprocs=2
```

## Resursiem pielāgota pieņemšana

Darbinieki dara vairāk nekā tikai pārņem nākamo gaidošo rindu. Pirms pārņemtā darba sākšanas Queuety var veikt sākotnējās piekļuves pārbaudes, pamatojoties uz darba vienlaicīguma grupu un neseno šī apstrādātāja izpildes profilu.

Plašāku modeļa aprakstu, tostarp to, kā tas saistīts ar darbu metadatiem un darbplūsmu budžetiem, skatiet sadaļā [Resursu pārvaldība](https://queuety.inline0.dev/lv/docs/features/resource-management).

Vienlaicīguma grupa nosaka kopīgu limitu vairākiem apstrādātājiem vai darbu klasēm. Ja vairākiem resursietilpīgiem pakalpojumu sniedzējiem piešķirat vienu un to pašu grupu un limitu, darbinieks atbrīvos tikko pārņemto darbu, nevis sāks to, kad grupas limits būs sasniegts. Tādējādi neatkarīgas rindas vienlaikus nepārslogo vienu pakārtoto sistēmu tikai tāpēc, ka ir vairāki dīkstāvē esoši darbinieki.

Nesenie izpildes žurnāli arī nodrošina vienkāršu piekļuves profilu. Ja ir iespējota resursu piekļuves kontrole, Queuety aplūko neseno vidējo ilgumu un šobrīd darbināmā apstrādātāja maksimālo atmiņas patēriņu. Ja pašreizējais darbinieks jau tuvojas konfigurētajam atmiņas limitam, rindas vai pakalpojumu sniedzēju grupas svērtais budžets jau ir izsmelts, pašreizējā konteinerā, šķiet, nepietiek atlikušās atmiņas šī apstrādātāja novērotajam profilam vai `--once` tipa izpilde tuvojas laika limitam, Queuety atliek darbu, nevis sāk izpildi, kas, visticamāk, netiks pabeigta bez problēmām.

Šo politiku ieslēdziet darba definīcijā, nevis darbinieka komandā:

```php
class CallProviderStep implements \Queuety\Step {
    public function handle( array $state ): array {
        // ...
    }

    public function config(): array {
        return [
            'concurrency_group' => 'providers',
            'concurrency_limit' => 3,
            'cost_units' => 5,
        ];
    }
}
```

Šos pašus metadatus var pievienot izpildāmu darbu klasēm ar publiskiem rekvizītiem vai atsevišķai izpildei, izmantojot `PendingJob::concurrency_group()` un `PendingJob::cost_units()`.

Darbinieka puses piekļuves profilu kontrolē šīs konstantes:

| Konstante | Apraksts |
|---|---|
| `QUEUETY_RESOURCE_ADMISSION` | Iespējot vai atspējot piekļuves pārbaudes, kas balstītas uz profilu |
| `QUEUETY_RESOURCE_PROFILE_WINDOW_MINUTES` | Cik tālu pagātnē meklēt, veidojot nesenos apstrādātāju profilus |
| `QUEUETY_RESOURCE_PROFILE_TTL` | Nesenā apstrādātāja profila kešatmiņas TTL |
| `QUEUETY_RESOURCE_MEMORY_HEADROOM_MB` | Rezervētā atmiņa pirms nākamā darba pieņemšanas |
| `QUEUETY_RESOURCE_SYSTEM_MEMORY_AWARENESS` | Iespējot vai atspējot aptuvenas konteinera vai resursdatora atmiņas pārbaudes |
| `QUEUETY_RESOURCE_SYSTEM_MEMORY_HEADROOM_MB` | Rezervētā sistēmas atmiņa pirms nākamā darba pieņemšanas |
| `QUEUETY_RESOURCE_QUEUE_COST_BUDGETS` | Svērtie izmaksu budžeti pēc rindas nosaukuma |
| `QUEUETY_RESOURCE_GROUP_COST_BUDGETS` | Svērtie izmaksu budžeti pēc `concurrency_group` |
| `QUEUETY_RESOURCE_TIME_HEADROOM_MS` | Rezervētais laika limits vienreizējām darbinieka izpildēm |

## Darbinieka dzīves cikls

Darbinieks pēc pašreizējā darba pabeigšanas pārtrauc darbību korekti, ja ir izpildīts kāds no šiem nosacījumiem:

| Nosacījums | Konfigurācija |
|---|---|
| Maksimālais apstrādāto darbu skaits | `QUEUETY_WORKER_MAX_JOBS` (pēc noklusējuma: 1000) |
| Pārsniegts atmiņas limits | `QUEUETY_WORKER_MAX_MEMORY` (pēc noklusējuma: 128 MB) |

Pēc apstāšanās darbinieks tiek korekti izslēgts. Produkcijas vidē procesu pārvaldnieks to automātiski palaiž no jauna.

Signāli vēl netiek apstrādāti korekti ([#4](https://github.com/inline0/queuety/issues/4)). Atsevišķs `wp queuety work` process neiestata signālu apstrādātāju, tāpēc `SIGTERM` vai `SIGINT` (Ctrl+C) to nekavējoties pārtrauc, pat ja darbs vēl nav pabeigts. Šis darbs paliek `processing`, līdz novecojušo darbu atkopšana to atiestata pēc `QUEUETY_STALE_TIMEOUT` sekundēm, tāpēc apstrādātājiem jābūt drošiem atkārtotai palaišanai. Darbinieku kopa pārsūta `SIGTERM` saviem pakārtotajiem procesiem, taču tie uz to nereaģē, tāpēc kopa turpina darboties, līdz procesi apstājas kāda iepriekš minētā iemesla dēļ. Ja jāaptur kopa, iestatiet procesu pārvaldniekam apstāšanās noildzi, pēc kuras tas nosūta `SIGKILL`.

## Vairāku darbinieku vienlaicīga izpilde

Karodziņš `--workers=N` palaiž N pakārtotos procesus, izmantojot `pcntl_fork()`. Katrs pakārtotais process izveido savu datubāzes savienojumu un apstrādā darbus neatkarīgi. Galvenais process uzrauga pakārtotos procesus un no jauna palaiž tos, kas avarē.

```bash
wp queuety work --queue=default --workers=4
```

Prasības:
Jābūt instalētiem `pcntl` un `posix` PHP paplašinājumiem (bez `pcntl` komanda neizdodas ar kļūdu "pcntl extension is required for --workers=N."), un katrs pakārtotais process izmanto savu datubāzes savienojumu, tāpēc iestatījumā MySQL `max_connections` jāparedz pietiekami daudz savienojumu visai darbinieku kopai. Adaptīvajām kopām (`--min-workers`/`--max-workers`) ir tādas pašas prasības.

## Adaptīvas darbinieku kopas

Adaptīvās kopas uztur vismaz noteiktu skaitu aktīvu darbinieku un pēc tam palielinās vai samazinās konfigurētajās robežās:

```bash
wp queuety work --queue=providers --min-workers=2 --max-workers=6
```

Galvenais process uzrauga apstrādei pieejamo darbu uzkrājumu atlasītajās rindās un pielāgo pakārtoto procesu skaitu šim uzkrājumam, nepārsniedzot konfigurēto maksimumu. Kad rinda kļūst mierīga, kopa nogaida dīkstāves periodu, pirms samazina darbinieku skaitu, lai īslaicīgi darba pieplūdumi uzreiz neizraisītu procesu saraksta izmaiņas.

Mērogošana joprojām ir piesardzīga. Ja Queuety var nolasīt konteinera vai resursdatora atmiņas datus, tas nepievieno pakārtotus procesus, ja atlikusī atmiņa nav pietiekama vēl viena pilna darbinieka resursu limitam.

Galvenā procesa mērogošanas ciklu kontrolē:

| Konstante | Apraksts |
|---|---|
| `QUEUETY_WORKER_POOL_SCALE_INTERVAL` | Cik bieži galvenais process saskaņo kopas lielumu |
| `QUEUETY_WORKER_POOL_IDLE_GRACE` | Cik ilgi uzkrājumam jābūt neaktīvam, pirms samazināt kopas lielumu |

## Novecojušu darbu atkopšana

Ja darbinieks avarē, apstrādājot darbu, tā statuss paliek `processing`. Ilgstoši darbojošs darbinieks aptuveni reizi minūtē pārbauda, vai nav darbu, kas `processing` atradušies ilgāk par `QUEUETY_STALE_TIMEOUT` sekundēm. Novecojis darbs, kam vēl ir atlikuši mēģinājumi, tiek mēģināts vēlreiz pēc gaidīšanas perioda; darbs, kam visi mēģinājumi jau izmantoti, tiek paslēpts, un tā darbplūsma tiek atzīmēta kā neveiksmīga. `--once` darbinieki un WP-Cron rezerves mehānisms šo pārbaudi neveic.

Novecojušos darbus var atkopt manuāli:

```bash
wp queuety recover
```

## Iztukšošanas režīms

Apstrādā visus gaidošos darbus un iziet. Noder testēšanai vai vienreizējai pakešapstrādei:

```bash
wp queuety flush
wp queuety flush --queue=emails
```

## Izvietošana produkcijas vidē

Produkcijas vidē izmantojiet procesu pārvaldnieku, lai darbinieki turpinātu darboties. Tālāk aprakstīti divi izplatīti risinājumi.

### Supervisord

```ini
[program:queuety-default]
command=wp queuety work --queue=default
directory=/var/www/html
autostart=true
autorestart=true
numprocs=2
process_name=%(program_name)s_%(process_num)02d
stdout_logfile=/var/log/queuety-default.log
stderr_logfile=/var/log/queuety-default-error.log

[program:queuety-emails]
command=wp queuety work --queue=emails
directory=/var/www/html
autostart=true
autorestart=true
numprocs=1
stdout_logfile=/var/log/queuety-emails.log
stderr_logfile=/var/log/queuety-emails-error.log
```

### Systemd

```ini
[Unit]
Description=Queuety Worker (default queue)
After=mysql.service

[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/html
ExecStart=/usr/local/bin/wp queuety work --queue=default
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
```

Iespējojiet un palaidiet:

```bash
sudo systemctl enable queuety-worker
sudo systemctl start queuety-worker
```

### Izvietošanas ieteikumi

Ja nepieciešama stingrāka izolācija, katrai rindai palaidiet atsevišķus darbiniekus. Izmantojiet `--workers=N`, ja darba slodze galvenokārt noslogo procesoru, bet, ja tā galvenokārt izmanto ievadi/izvadi, priekšroku dodiet atsevišķi uzraudzītiem darbiniekiem. Iestatiet `QUEUETY_WORKER_MAX_JOBS`, ja vēlaties periodiski restartēt procesus, lai atbrīvotu atmiņu, un sekojiet līdzi `buried` skaitam, izmantojot [tīmekļa āķus](https://queuety.inline0.dev/lv/docs/features/webhooks) vai [mērījumus](https://queuety.inline0.dev/lv/docs/features/metrics).
