Skip to content

Meduse Catalog Import ​

This page traces the Magento-side catalog consumer at source commit 3edcc1e24e9a1e8382dc1bad0dfb3158b8074cea. Start with Product creation to storefront for the complete source-level loop, or Meduse publication for the producer and acknowledgement reader. Deployed configuration and runtime acceptance remain unverified.

Flow ​

View diagram source
flowchart LR
  MED_SRC["Meduse feed producer<br/>(see Meduse publication guide)"] -->|JSONL feed| P["FTP root + export/pending"]
  P --> JOB["axelites_meduse_syncproducts<br/>every 5 minutes; up to 4 files"]
  JOB --> PROC["export/processing<br/>move before read"]
  PROC --> SKU{"Find by SKU"}
  SKU -->|new| CREATE["Create simple product<br/>attributes, stock, websites"]
  SKU -->|existing| UPDATE["Update mapped product data"]
  CREATE --> ACK["Write updated_<feed>.csv<br/>under export/complete"]
  UPDATE --> ACK
  ACK -->|Magento IDs and derived fields| MED_ACK["Meduse acknowledgement reader<br/>(see Meduse publication guide)"]
  PROC -. "exceptions and row failures" .-> LOG["var/log/meduse.log<br/>no failed folder"]
  CREATE --> SEARCH["Typesense update call<br/>then targeted indexers"]
  UPDATE --> SEARCH

Diagram

The scheduled consumer is Axelites\Meduse\Cron\SyncProducts::execute, registered as axelites_meduse_syncproducts in the meduse cron group with */5 * * * *. It lists *.jsonl from the pending directory, takes at most the first four entries returned by FTP, moves those entries to processing, and reads only that batch. See the pinned cron registration and consumer.

Roots and entry points ​

Magento reads the FTP root from the admin configuration key meduse/general/meduse_ftp_path. The normal product feed folders are formed by appending export/pending, export/processing, and export/complete to that configured prefix. The active configured value is environment data and was not inspected. A cleanup helper hardcodes /meduse/connectors/menzzo/export/processing instead of using that setting, so it can diverge from the configured root. The FTP host, username, password, and media URL are configuration inputs; their values are intentionally omitted. The source fields and configuration lookup are visible in System Configuration and Helper\Data.

The module also registers these cron jobs, all on the same five-minute schedule: axelites_meduse_syncAttributes, axelites_meduse_savefamily, axelites_meduse_sync_files, axelites_meduse_save_product_images, axelites_meduse_save_product_family, and axelites_meduse_sync_meduse_menu. Their separate payloads and side effects are covered in Catalog dependencies.

There is no CLI catalog importer registered in this module. The registered command menzzo:meduse:export-portuguese-products runs in the opposite direction: it writes a Magento product export to Magento's var/products_portugale.jsonl file and does not upload that file to FTP. See the command registration and export command.

Product create and update behavior ​

Each non-empty JSONL line is decoded as one product record. Magento looks up catalog_product_entity by SKU. A missing SKU enters createProduct(), which directly inserts a simple-product entity, starts its stock at quantity 1000, creates flat rows where possible, assigns mapped websites plus website 1, and returns the new entity ID. An existing SKU is updated in place. Mapped attributes are written through catalog EAV tables, categories are reconciled against the category mapping, and the family mapping can set the attribute set. This is direct database work in this cron, not a Magento repository save. See SKU handling and row updates and product creation.

For existing products older than two days, the importer skips status and visibility from the incoming attributes and skips several fields reserved for creation. It applies status for new products and products created within the preceding two days. Newly created AsirGroup products receive a later visibility and zero-stock override; newly created Notio products receive a later visibility override. Those overrides happen after the targeted reindex calls in this method. The exact branch and overrides are in attribute filtering and status handling, status and visibility filtering, and post-import overrides.

New products can have images applied from the product JSONL payload. A separate image CSV consumer updates existing SKUs under export-product-images/{pending,processing,complete}; a product-file CSV consumer uses export-product-files/{pending,processing,complete}. Both use the same configured FTP prefix. On the Magento host, product images are stored under DirectoryList::MEDIA/catalog/product/<relative-path> (normally pub/media/catalog/product); product documents go under DirectoryList::MEDIA/fiche-produit/dim-produit/ or DirectoryList::MEDIA/fiche-produit/notice/. The URL used to fetch media is configuration-driven and is not reproduced here. See product image intake, image storage, and product file handling.

Acknowledgement, indexing, and UI evidence ​

For rows that reach response construction, Magento adds an acknowledgement row before it updates mapped attributes, categories, and images. The response includes SKU, feed ID, Magento entity ID, shipping and parcel data, availability, Google product category/type, and MPN. The feed ID is the product's ancien_id value when present, otherwise the Magento entity ID. Magento writes updated_<input-name>.csv to the FTP export/complete folder, then removes the input JSONL from export/processing; it does not move the input file to a success folder. See response row construction and file write and completion and input removal.

After rows are processed, the cron calls the Typesense update helper and attempts per-product reindexing for category/product relations, product attributes, stock, search, price, and catalog rules. Indexer failures are logged and the loop continues. This code does not call Magento cache clean or flush. See the indexer list and failure handling. These are source-level actions only; they do not prove that an Admin product page, storefront product page, search result, or external Meduse acknowledgement reader displayed or accepted the product.

The admin configuration exposes an enabled field and the helper has an isEnabled() accessor. The main product cron reads the FTP configuration but does not check that accessor; the cron entry path contains no isEnabled() check, while Helper\Data only defines the accessor. Therefore the presence or value of the configuration field is not evidence that the import cron is gated by it.

Failure and duplicate cases ​

CaseSource behaviorWhat to verify
Repeated SKU or replayed feedLookup is by SKU, so later rows or replayed files take the existing-product branch. There is no file-level or row-level deduplication.Check the final persisted SKU fields and the returned acknowledgement row. A repeated SKU can be updated more than once in one file. See SKU lookup.
Malformed JSON lineThe line is logged and skipped; the worker continues with other lines. No dedicated error file is written.Compare input line count with acknowledgement rows and inspect the Magento Meduse log through an approved environment procedure. See JSONL parsing.
Row update throwsThe exception is logged and processing continues. Earlier writes in that row are not shown as transactional, and a response row may already have been assembled.Treat an acknowledgement ID as correlation only; verify the product attributes, category, image, stock, and index state separately. See response before later row work and row exception handler.
Empty or unreadable JSONLAn empty read continues before response creation and before the normal processing-file removal.Check whether the file remains in processing and whether any acknowledgement was produced. See empty-read and removal branches.
Indexer failureThe failing indexer is logged; later indexers are still attempted. The acknowledgement may already exist.Verify the affected indexer's state and storefront/search result independently. See indexer handling.
FTP move or response write failsReturn values are not checked. Even a caught response-write exception can be followed by input deletion.Correlate the actual input and response files; absence of the input does not prove a usable acknowledgement exists.
Attribute lock timeout repeats five timesThe bounded retry loop can exhaust and continue without rethrowing a final error.Check persisted attributes; a completion row does not certify that the retry succeeded.
File stranded in processingThe importer processes only files selected from pending during the current invocation.A later Magento invocation does not retry every processing file. Meduse has a separate hourly stale-file recycler; see Meduse publication.
Image sidecar failureIts failure path logs the error and leaves the failed-file move commented out; a non-empty image payload clears current gallery entries before adding replacements.Compare gallery entries and the image file in Magento media storage. See image save and failure branches and Catalog dependencies.

The importer has no explicit failed or error directory. File-level and row-level exceptions are written to var/log/meduse.log; this documents the source's logging target, not a recommendation to read production logs without approval. A completion CSV can coexist with skipped or partially processed rows, so completion-file presence is not a full success signal.

Completion boundary ​

Source review proves the Magento consumer's registration, FTP path construction, SKU-based create/update branches, response-file write, media destinations, and attempted indexing at the pinned commit. It does not prove a current deployment, the environment's configured FTP prefix, a successful cron run or Admin/storefront availability. The producer and acknowledgement reader are traced separately in the linked Meduse guide. Confirm those runtime boundaries separately in an approved non-production environment before treating an import as accepted.

Internal developer documentation for Menzzo systems.