Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Commercetools Async Pool Bundle Laravel Package

bestit/commercetools-async-pool-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require bestit/commercetools-async-pool-bundle
    

    Ensure your project uses Symfony 4+ (or 3.x with Flex) and Composer.

  2. Enable the Bundle: Add to config/bundles.php (Symfony 4+):

    return [
        // ...
        BestIt\CTAsyncPoolBundle\BestItCTAsyncPoolBundle::class => ['all' => true],
    ];
    

    (Note: The README mentions AppKernel.php, but Symfony 4+ uses bundles.php.)

  3. First Use Case: Inject the async pool service into a controller or command:

    use BestIt\CTAsyncPoolBundle\Service\AsyncPoolService;
    
    class MyController extends AbstractController
    {
        public function __construct(private AsyncPoolService $asyncPool)
        {
        }
    
        public function executeAsyncRequest()
        {
            $this->asyncPool->addRequest(
                new AsyncRequest(
                    'POST',
                    '/api/v2/products',
                    ['key' => 'test-product'],
                    ['name' => 'Test Product']
                )
            );
            // Requests are queued and flushed automatically.
        }
    }
    
  4. Key Files to Review:

    • config/packages/bestit_ct_async_pool.yaml (if auto-generated).
    • src/Service/AsyncPoolService.php (core service).
    • Event listeners in src/EventListener/.

Implementation Patterns

Core Workflow: Async Request Handling

  1. Queueing Requests: Use AsyncPoolService to queue requests without immediate execution:

    $this->asyncPool->addRequest(
        new AsyncRequest(
            method: 'GET',
            path: '/api/v2/customers/{id}',
            query: ['expand' => 'orders'],
            body: null,
            headers: ['Authorization' => 'Bearer ...']
        )
    );
    
    • Supports GET, POST, PUT, PATCH, DELETE.
    • Replace path placeholders (e.g., {id}) with actual values via setPathVariables().
  2. Batching Requests: Group related requests (e.g., bulk product updates) into a single batch:

    $this->asyncPool->startBatch();
    $this->asyncPool->addRequest(...); // Request 1
    $this->asyncPool->addRequest(...); // Request 2
    $this->asyncPool->endBatch();
    
    • Batches are flushed together to reduce overhead.
  3. Event-Driven Flushing: The bundle auto-flushes the pool on:

    • Kernel termination (kernel.terminate event).
    • Custom events (e.g., async_pool.flush). Override via configuration:
    # config/packages/bestit_ct_async_pool.yaml
    bestit_ct_async_pool:
        flush_events:
            - 'kernel.terminate'
            - 'custom.event.name'
    
  4. Integration with Commercetools SDK: Pair with commercetools/sdk for structured requests:

    use Commercetools\Sdk\Client\ClientBuilder;
    use Commercetools\Sdk\Request\CreateRequest;
    
    $client = ClientBuilder::withClientCredentials(...);
    $request = new CreateRequest($client, 'products', ['key' => 'test']);
    $this->asyncPool->addRequest(
        new AsyncRequest(
            'POST',
            '/api/v2/products',
            [],
            $request->getBody()
        )
    );
    
  5. Error Handling: Configure retry logic or error callbacks:

    bestit_ct_async_pool:
        retry_config:
            max_attempts: 3
            delay: 100 # ms
        error_listener: App\Listener\AsyncPoolErrorListener
    

Gotchas and Tips

Pitfalls

  1. Kernel Compatibility:

    • Symfony 3.x: Use AppKernel.php as in the README.
    • Symfony 4+: Use config/bundles.php (ignore AppKernel.php).
    • Symfony 5.1+: Ensure auto_wiring is enabled in config/services.yaml for dependency injection.
  2. Request Validation:

    • The bundle does not validate request structure (e.g., missing path or method).
    • Always validate inputs before queuing:
      if (empty($request->getPath())) {
          throw new \InvalidArgumentException('Path is required.');
      }
      
  3. Event Listener Overrides:

    • If extending the bundle, avoid overriding the default FlushPoolListener unless you need custom flush logic.
    • Instead, use the async_pool.flush event to react to flushes:
      // src/EventListener/CustomFlushListener.php
      public function onFlush(AsyncPoolFlushEvent $event) {
          $event->addPostFlushCallback(function () {
              // Run after flush (e.g., log completion).
          });
      }
      
  4. Thread Safety:

    • The pool is not thread-safe by default. For multi-threaded environments (e.g., Symfony Messenger), use a lock:
      $this->asyncPool->addRequest(..., ['lock' => true]);
      
  5. Configuration Overrides:

    • Default config is in src/Resources/config/services.yaml. Override via:
      # config/packages/bestit_ct_async_pool.yaml
      bestit_ct_async_pool:
          pool_size: 20       # Default: 10
          timeout: 30000      # ms (default: 10000)
      

Debugging Tips

  1. Enable Logging: Add to config/packages/monolog.yaml:

    handlers:
        async_pool:
            type: stream
            path: "%kernel.logs_dir%/async_pool.log"
            level: debug
            channels: ["async_pool"]
    

    Then configure the bundle to use the channel:

    bestit_ct_async_pool:
        logger_channel: async_pool
    
  2. Inspect Queued Requests: Access the raw pool via:

    $pool = $this->asyncPool->getPool();
    foreach ($pool->getRequests() as $request) {
        var_dump($request->getMethod(), $request->getPath());
    }
    
  3. Common Errors:

    • "Pool already flushed": Ensure you’re not manually flushing ($this->asyncPool->flush()) and relying on auto-flush.
    • Timeout errors: Increase timeout in config if commercetools responses are slow.
    • Circular dependencies: Avoid injecting AsyncPoolService into event listeners that trigger flushes.

Extension Points

  1. Custom Request Classes: Extend AsyncRequest to add metadata:

    class CustomAsyncRequest extends AsyncRequest
    {
        private $priority;
    
        public function __construct($method, $path, array $query = [], array $body = [], array $headers = [], $priority = 0)
        {
            parent::__construct($method, $path, $query, $body, $headers);
            $this->priority = $priority;
        }
    
        public function getPriority() { return $this->priority; }
    }
    

    Then register the class in config:

    bestit_ct_async_pool:
        request_class: App\Request\CustomAsyncRequest
    
  2. Middleware Support: Add request/response middleware via the AsyncPoolService:

    $this->asyncPool->addMiddleware(function (AsyncRequest $request, callable $next) {
        $request->addHeader('X-Custom-Header', 'value');
        return $next($request);
    });
    
  3. Async Pool Factory: For testing, replace the default pool with a mock:

    // config/services_test.yaml
    services:
        BestIt\CTAsyncPoolBundle\Service\AsyncPoolService:
            factory: ['@BestIt\CTAsyncPoolBundle\Service\AsyncPoolFactory', 'createTestPool']
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium