Claude Skill

bitrix-background-jobs

CAgent, addBackgroundJob, Messenger brokers/queues. Use for deferred and async processing.

LLM Mart · 0 points · 13 views 34 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download bxmaximum-bitrix-framework-skills-skills_bitrix-background-jobs-66c40e0.zip · 5 KB
Part of bxmaximum/bitrix-framework-skills — 38 skills

Install

skills CLI npx skills add https://github.com/bxmaximum/bitrix-framework-skills/tree/main/skills/bitrix-background-jobs
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install bxmaximum-bitrix-framework-skills@llmmart
Git git clone https://github.com/bxmaximum/bitrix-framework-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole bxmaximum/bitrix-framework-skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Background Tasks in Bitrix

Baseline: main 23.0+. Features newer than baseline are marked Since.

Progressive disclosure: open only the rule files that match the task. Do not read every rules/*.md.

How to use

  1. Identify the layer the task touches.
  2. Open the matching rules/*.md below.
  3. Prefer framework-native Bitrix patterns over custom abstractions.

Choose a rule file

When to read rules/agents.md

Read rules/agents.md (CAgent agents) when the task involves:

  • Agents (CAgent)

When to read rules/background-job.md

Read rules/background-job.md (Application::addBackgroundJob) when the task involves:

  • Application::addBackgroundJob()

When to read rules/messenger.md

Read rules/messenger.md (Messenger queues) when the task involves:

  • Messenger (Message Queues)
  • When to Choose What
  • Checklist

Checklist

  • Opened only the rule file(s) needed for this task.
  • Followed DI / /local/ / security canons from AGENTS.md.
Files (bitrix-framework-skills)
  • rules
    • agents.md 2.3 KB
      # CAgent agents
      
      ## Agents (`CAgent`)
      
      ```php
      \CAgent::AddAgent(
          name: \Vendor\Module\Cli\Agent\QueueAgent::class . '::run();',
          module: 'vendor.module',
          period: 'N',        // 'Y' — periodic (always by interval), 'N' — shift next_exec
          interval: 300,      // seconds
          datecheck: '',
          active: 'Y',
          next_exec: '',
          sort: 100,
          existError: true,
      );
      ```
      
      Agent method:
      
      ```php
      namespace Vendor\Module\Cli\Agent;
      
      final class QueueAgent
      {
          public static function run(): string
          {
              \Bitrix\Main\Loader::includeModule('vendor.module');
              \Bitrix\Main\DI\ServiceLocator::getInstance()
                  ->get(\Vendor\Module\Application\Service\QueueProcessor::class)
                  ->processBatch(limit: 100);
      
              return self::class . '::run();'; // important: return string for re-registration
          }
      }
      ```
      
      ### Rules
      
      - An agent works either on hits or via cron (Admin Panel → Agent Settings).
      - For heavy agents **always** enable cron — otherwise they block user hits.
      - An agent running longer than 10 minutes is blocked by the kernel.
      - Periodic (`period = 'Y'`) vs non-periodic (`period = 'N'`) agents differ in how `next_exec` is calculated.
      - In module's `DoUninstall`: `CAgent::RemoveModuleAgents('vendor.module')`.
      - Do not keep state in statics between calls — the process may change.
      - Combine `addBackgroundJob` for immediate post-response work with `CAgent` for scheduled retries.
      
      ### Multisite
      
      Agents are shared across the whole installation: stored in one database, executed from one common list, with no filtering by site. An agent does not run per site and gets no user/site context.
      
      - Never rely on `SITE_ID` (or any current-site/user context) inside an agent function.
      - If the logic is site-specific, pass the site ID explicitly in the agent call: `\Vendor\Module\Cli\Agent\SyncAgent::class . "::run('s2');"` — one registered agent per site if needed.
      - When moving agents to cron, do **not** create identical cron jobs per site — cron runs the shared agent list and cannot inject a site context.
      
      ### One-time task for "in 5 minutes"
      
      ```php
      \CAgent::AddAgent(
          \Vendor\Module\Cli\Agent\SendEmailAgent::class . "::run({$userId});",
          'vendor.module',
          'N',
          60,
          '',
          'Y',
          (new \Bitrix\Main\Type\DateTime())->add('+5 minutes')->toString(),
      );
      ```
      
    • background-job.md 1002 B
      # Application::addBackgroundJob
      
      ## `Application::addBackgroundJob()`
      
      Deferred call **after** sending the response (before `fastcgi_finish_request` / in `onAfterEpilog`). Ideal for metrics, welcome emails, or other short tail work.
      
      Signature: `addBackgroundJob(callable $job, array $args = [], $priority = Application::JOB_PRIORITY_NORMAL)`.
      
      Priorities:
      
      | Constant | Value |
      | --- | --- |
      | `Application::JOB_PRIORITY_NORMAL` | `100` |
      | `Application::JOB_PRIORITY_LOW` | `50` |
      
      ```php
      use Bitrix\Main\Application;
      
      Application::getInstance()->addBackgroundJob(
          static function () use ($userId): void {
              \Vendor\Module\Application\Service\Notifier::fromContainer()->sendWelcome($userId);
          },
          [],
          Application::JOB_PRIORITY_NORMAL,
      );
      ```
      
      ### Constraints
      
      - Still a single PHP process. Long tasks degrade worker release time.
      - No delivery guarantee: if the process crashes — the task won't execute.
      - Not suitable if retries and parallelism are needed — use `Messenger`.
      
    • messenger.md 7.6 KB
      # Messenger queues
      
      ## Messenger (Message Queues)
      
      > **Alpha status** (**Since main 25.100.300**): API may change without backward compatibility guarantees. Use with caution in production.
      
      Queue = logical channel from sender to handler. Message → broker → receiver processes it.
      
      Components: **message** (DTO), **handler** (`AbstractReceiver`), **broker** (storage), **queue** (named handler binding).
      
      ### 1. Message (DTO)
      
      ```bash
      php bitrix/bitrix.php make:message SendWelcomeEmail -m vendor.module
      ```
      
      ```php
      namespace Vendor\Module\Public\Message;
      
      use Bitrix\Main\Messenger\Entity\AbstractMessage;
      use Bitrix\Main\Messenger\Entity\MessageInterface;
      
      final class SendWelcomeEmailMessage extends AbstractMessage
      {
          public function __construct(
              public readonly int $userId,
              public readonly string $email,
          ) {}
      
          public static function createFromData(array $data): MessageInterface
          {
              return new self(...$data);
          }
      }
      ```
      
      Requirements:
      - JSON-serializable data only: `string`, `int`, `float`, `bool`, `array`.
      - Implement `jsonSerialize()` for complex structures.
      - Include all data needed at processing time (entity may be deleted before delayed handling).
      
      ### 2. Handler
      
      ```bash
      php bitrix/bitrix.php make:messagehandler SendWelcomeEmail \
          --message-module=vendor.module --handler-module=vendor.module
      ```
      
      (`make:messagehandler` uses **`--message-module`**, not `--event-module`. The latter belongs to `make:eventhandler`.)
      
      ```php
      namespace Vendor\Module\Internals\Messenger\Receiver;
      
      use Bitrix\Main\Messenger\Entity\MessageInterface;
      use Bitrix\Main\Messenger\Receiver\AbstractReceiver;
      use Bitrix\Main\Messenger\Internals\Exception\Receiver\UnprocessableMessageException;
      use Vendor\Module\Public\Message\SendWelcomeEmailMessage;
      
      final class SendWelcomeEmailHandler extends AbstractReceiver
      {
          public function __construct(
              private readonly \Vendor\Module\Application\Service\Mailer $mailer,
          ) {
              parent::__construct();
          }
      
          protected function process(MessageInterface $message): void
          {
              if (!$message instanceof SendWelcomeEmailMessage) {
                  throw new UnprocessableMessageException($message);
              }
      
              $this->mailer->sendWelcome($message->userId, $message->email);
          }
      }
      ```
      
      **Handler MUST be registered in module `services`** — `QueueConfig::createReceiver()` resolves it via `ServiceLocator::get($handler)`:
      
      ```php
      // /local/modules/vendor.module/.settings.php
      'services' => [
          'value' => [
              \Vendor\Module\Internals\Messenger\Receiver\SendWelcomeEmailHandler::class => [
                  'className' => \Vendor\Module\Internals\Messenger\Receiver\SendWelcomeEmailHandler::class,
              ],
              // or constructor closure / autowire as usual
          ],
          'readonly' => true,
      ],
      ```
      
      Handler rules:
      - Extend `AbstractReceiver`, implement **`protected function process()`** (not `handle()`).
      - Return `void` on success; throw on failure.
      - Exception types (namespace `Bitrix\Main\Messenger\Internals\Exception\Receiver\`):
        - `UnprocessableMessageException` — wrong message type (`__construct(MessageInterface $messengerMessage, ...)`)
        - `UnrecoverableMessageException` — no retry
        - `RecoverableMessageException` — temporary, optional `getRetryDelay()`
      
      ### 3. Dispatching
      
      ```php
      $message = new SendWelcomeEmailMessage($userId, $email);
      $message->send('vendor_module_queue');
      
      // Delayed processing (1 hour):
      use Bitrix\Main\Messenger\Entity\ProcessingParam\DelayParam;
      use Bitrix\Main\Messenger\Entity\ProcessingParam\ItemIdParam;
      
      $message->send('vendor_module_queue', [
          new DelayParam(3600),
          new ItemIdParam('welcome-' . $userId),
      ]);
      ```
      
      Do **not** use `MessageBus::dispatch()` — the current API is `$message->send('queue_name')`.
      
      ### 4. Configuration in `.settings.php`
      
      Global config (`/bitrix/.settings.php` or `/local/.settings.php`) — brokers and cross-module queues:
      
      ```php
      'messenger' => [
          'value' => [
              'run_mode' => 'web', // 'web' — background jobs on hit; 'cli' — requires messenger:consume
              'brokers' => [
                  'default' => [
                      'type' => 'db',
                      'params' => [
                          'table' => \Bitrix\Main\Messenger\Internals\Storage\Db\Model\MessengerMessageTable::class,
                      ],
                  ],
              ],
              'queues' => [
                  'vendor_module_queue' => [
                      'handler' => \Vendor\Module\Internals\Messenger\Receiver\SendWelcomeEmailHandler::class,
                  ],
              ],
          ],
          'readonly' => true,
      ],
      ```
      
      Module config (`/local/modules/vendor.module/.settings.php`) — module-specific queues:
      
      ```php
      'messenger' => [
          'value' => [
              'queues' => [
                  'vendor_module_queue' => [
                      'handler' => \Vendor\Module\Internals\Messenger\Receiver\SendWelcomeEmailHandler::class,
                      'limit' => 10,                    // messages per batch (default 50)
                      'total_processing_limit' => 50,     // max concurrent, default 100; must be >= limit (else ArgumentOutOfRangeException at consume)
                      'retry_strategy' => [
                          'max_retries' => 3,
                          'delay' => 5,
                          'multiplier' => 2,
                          'max_delay' => 300,
                      ],
                  ],
              ],
          ],
          'readonly' => true,
      ],
      ```
      
      Notes:
      - Only broker type **`db`** is supported currently (not Redis/Doctrine DSN).
      - The `default` broker must always exist in global config.
      - Put queues in the module `.settings.php` they belong to; global config only for cross-module queues.
      - Custom broker table: extend `MessengerMessageTable`, register in `brokers`, create table in module installer.
      - Queue `handler` FQCN must also exist under module `services` (see above).
      - `limit` default **50**, `total_processing_limit` default **100**. Consume throws `ArgumentOutOfRangeException` if `limit > total_processing_limit`.
      
      ### 5. Consumer (CLI mode)
      
      Set `'run_mode' => 'cli'` and run under Supervisor/systemd:
      
      ```bash
      php bitrix/bitrix.php messenger:consume vendor_module_queue \
          --time-limit=300 --sleep=1
      ```
      
      Flags:
      - `-t, --time-limit` — process lifetime in seconds.
      - `--sleep` — pause between iterations when queue is empty (default 1).
      
      Queue names are separate CLI arguments (`messenger:consume q1 q2`), not a comma-separated string. There is **no** `--limit` option in main 26.650.100 (it is commented out in `ConsumeMessagesCommand`); set `limit` / `total_processing_limit` on the queue in `.settings.php`.
      
      For production with heavy queues, prefer `cli` mode with a supervisor over `web` mode.
      
      ## When to Choose What
      
      - **Periodic task by schedule** → `CAgent` + cron mode.
      - **"Almost instant" tail after response** (email notification, metric) → `addBackgroundJob`.
      - **Reliable processing with retries, high volumes, parallelism** → `Messenger` (**Since 25.100.300**, alpha).
      - **Very long one-time data migration** → console command run manually.
      
      ## Checklist
      
      - [ ] Background code does not rely on `$_SESSION`/`$_COOKIE` in the hit context.
      - [ ] Agents registered by the module are removed in `DoUninstall`.
      - [ ] For CLI queues, `time-limit`, supervisor restart, and `run_mode=cli` are configured.
      - [ ] Messages contain scalars/DTOs with all data needed at processing time; no `EntityObject` with loaded relations.
      - [ ] Handler is registered in `services` and is idempotent: re-processing the same message is safe.
      - [ ] `total_processing_limit` >= `limit` in queue config.
      - [ ] Errors inside tasks are logged via PSR-3 logger, not silently suppressed.
      - [ ] `addBackgroundJob` uses `JOB_PRIORITY_NORMAL` (100) / `JOB_PRIORITY_LOW` (50), not arbitrary `0`.
      
  • SKILL.md 1.1 KB
    ---
    name: bitrix-background-jobs
    description: CAgent, addBackgroundJob, Messenger brokers/queues. Use for deferred and async processing.
    ---
    
    # Background Tasks in Bitrix
    
    Baseline: **main 23.0+**. Features newer than baseline are marked **Since**.
    
    Progressive disclosure: open **only** the rule files that match the task. Do not read every `rules/*.md`.
    
    ## How to use
    
    1. Identify the layer the task touches.
    2. Open the matching `rules/*.md` below.
    3. Prefer framework-native Bitrix patterns over custom abstractions.
    
    
    ## Choose a rule file
    
    ### When to read `rules/agents.md`
    
    Read `rules/agents.md` (`CAgent agents`) when the task involves:
    
    - Agents (`CAgent`)
    
    ### When to read `rules/background-job.md`
    
    Read `rules/background-job.md` (`Application::addBackgroundJob`) when the task involves:
    
    - `Application::addBackgroundJob()`
    
    ### When to read `rules/messenger.md`
    
    Read `rules/messenger.md` (`Messenger queues`) when the task involves:
    
    - Messenger (Message Queues)
    - When to Choose What
    - Checklist
    
    ## Checklist
    
    - [ ] Opened only the rule file(s) needed for this task.
    - [ ] Followed DI / `/local/` / security canons from `AGENTS.md`.
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related