adobe / commerce-integration-starter-kit

Adobe's integration starter kit uses Adobe Developer App Builder to improve real-time connection reliability and reduce the time-to-market for integrations between Adobe Commerce and other back-office systems, such as ERPs, CRMs, and PIMs.
Apache License 2.0
4 stars 2 forks source link

Event catalog_product_save_commit_after cannot serialize event data when dispatched from the REST API #16

Open brian-labelle opened 1 month ago

brian-labelle commented 1 month ago

This is more of an issue on the Adobe Commerce side, and it took a while to trace through, but I believe it's worth reporting here because this event is used in the starter kit, and will behave inconsistently

I noticed that when the observer event catalog_product_save_commit_after is dispatched from on Adobe Commerce admin panel, like saving the product, the event data is successfully added to the event_data table and can make its way to Adobe IO.

However, when the observer event catalog_product_save_commit_after is dispatched as the result of a REST API action, such as a PUT to /rest/default/V1/products/{sku}, the event_data record is never created

The reason is because an exception is getting thrown by \Magento\AdobeCommerceEventsClient\Event\Converter\EventDataConverter, which attempts to convert an event payload into JSON to add to the event_data table, which will then be picked up by the cron and sent to Adobe IO

The following exception occurs: Failed to save event data. Event code: "catalog_product_save_commit_after", Error: "Call to a member function toArray() on array"

For some reason, this doesn't happen when the item is saved in the admin panel. Something about the observer event payload must be different when called via the admin panel save vs the REST API call which triggers the ProductRepository save

The result is that we cannot get product update events triggered by REST API calls, but we can get them when the product is updated in the admin panel


Investigation

\Magento\AdobeCommerceEventsClient\Event\Converter\EventDataConverter::convertArray calls the following method: \Magento\Catalog\Model\Product::toArray

\Magento\Catalog\Model\Product::toArray has the following code:

public function toArray(array $arrAttributes = [])
{
    $data = parent::toArray($arrAttributes);
    $stock = $this->getStockItem();
    if ($stock) {
        $data['stock_item'] = $stock->toArray();
    }
    unset($data['stock_item']['product']);
    return $data;
}

The problem is, $data['stock_item'] = $stock->toArray(); failed because, at least in this context, $stock is actually already an array, so it cannot call toArray on it. Perhaps in the conversion process it was already converted? Perhaps when called from the REST API context, stock_item behaves differently?

Strangely, when saving this exact same product from the admin panel -- both from the All Stores context as well as a specific store-view context -- $stock = $this->getStockItem(); returns null, so the error does not occur

I have been able to reproduce this behavior on 2.4.7-p1 as well as 2.4.6-p3

brian-labelle commented 1 month ago

This issue appears to be fixed in this commit, but it's not part of the official Magento release yet: https://github.com/magento/magento2/commit/2f79a0695b8f1e02aad5f8e31ed7bdc9cd035533

It's part of 2.4.7-develop, but not 2.4.7-p1 or 2.4.7

rojoangel commented 1 month ago

@brian-labelle, if you don't have concerns, I'll wait for 2.4.7-p2 to be GA and close this issue.