bestit/commercetools-async-pool-bundle
Installation:
composer require bestit/commercetools-async-pool-bundle
Ensure your project uses Symfony 4+ (or 3.x with Flex) and Composer.
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.)
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.
}
}
Key Files to Review:
config/packages/bestit_ct_async_pool.yaml (if auto-generated).src/Service/AsyncPoolService.php (core service).src/EventListener/.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 ...']
)
);
GET, POST, PUT, PATCH, DELETE.{id}) with actual values via setPathVariables().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();
Event-Driven Flushing: The bundle auto-flushes the pool on:
kernel.terminate event).async_pool.flush).
Override via configuration:# config/packages/bestit_ct_async_pool.yaml
bestit_ct_async_pool:
flush_events:
- 'kernel.terminate'
- 'custom.event.name'
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()
)
);
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
Kernel Compatibility:
AppKernel.php as in the README.config/bundles.php (ignore AppKernel.php).auto_wiring is enabled in config/services.yaml for dependency injection.Request Validation:
path or method).if (empty($request->getPath())) {
throw new \InvalidArgumentException('Path is required.');
}
Event Listener Overrides:
FlushPoolListener unless you need custom flush logic.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).
});
}
Thread Safety:
$this->asyncPool->addRequest(..., ['lock' => true]);
Configuration Overrides:
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)
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
Inspect Queued Requests: Access the raw pool via:
$pool = $this->asyncPool->getPool();
foreach ($pool->getRequests() as $request) {
var_dump($request->getMethod(), $request->getPath());
}
Common Errors:
$this->asyncPool->flush()) and relying on auto-flush.timeout in config if commercetools responses are slow.AsyncPoolService into event listeners that trigger flushes.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
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);
});
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']
How can I help you explore Laravel packages today?