Conception de Workflows Pimcore pour l'Entreprise : L'Architecture Derrière 20 Éditeurs
Comment concevoir des workflows Pimcore pour les équipes entreprise. Séparation d'état en trois couches, propriété des champs, contrôle des événements, gestion des versions et sécurité des imports ERP.
Le probleme dont personne ne parle
Chaque installation Pimcore commence de la meme maniere. Quelques produits, une equipe de contenu de trois personnes, tout gere via l'interface admin. Publier signifie cliquer sur un bouton. La vie est simple.
Puis le systeme grandit. Vingt editeurs repartis sur plusieurs departements. Un ERP qui pousse des milliers de mises a jour produit chaque jour. Des workers en arriere-plan qui generent des miniatures, des PDF et des mises a jour d'index de recherche. Plusieurs canaux de sortie qui extraient des produits pour des audiences differentes. Un moteur de recherche qui synchronise chaque changement.
Et soudain, tout casse de manieres imprevues.
On a vecu ca directement sur un projet PIM entreprise pour un fabricant B2B dans la region DACH. Le systeme avait plusieurs event subscribers, divers workers asynchrones, une integration ERP poussant des imports quotidiens, et plusieurs canaux de sortie servant differents besoins metier. L'equipe avait grandi a plus de 20 editeurs, et l'architecture d'origine s'effondrait sous son propre poids.
Le probleme fondamental : le
save()de Pimcore est concu pour des editeurs humains, pas pour des systemes entreprise avec plusieurs processus automatises en competition pour les memes donnees.
Cet article couvre comment nous avons reconcu l'architecture des workflows de zero. Les patterns presentes ici s'appliquent a toute installation Pimcore qui depasse les bases. Pour un contexte plus large sur notre approche de l'architecture systeme et des implementations PIM, ces guides fournissent un contexte utile.
Pourquoi le modele par defaut de Pimcore casse a l'echelle
La persistance d'objets de Pimcore passe par un point d'entree unique :
$product->save();
Cela declenche une chaine de comportements implicites :
save()
-> PRE_UPDATE event fires (all subscribers, synchronous)
-> update() persists FULL object state to published tables
-> saveVersion() creates a version snapshot
-> POST_UPDATE event fires (all subscribers, synchronous)
-> Each subscriber may dispatch async messages
-> Each message handler may call save() again
-> Loop until supervisor or error breaks it
Chaque save() persiste l'objet entier. Pas le champ qui a change. L'objet entier. Ce design fonctionne bien pour des editeurs humains qui font des modifications occasionnelles. Il echoue quand tu as :
| Probleme | Ce qui se passe | Impact reel |
|---|---|---|
| Pas de controle de concurrence | Deux workers chargent le meme produit, chacun modifie un champ, les deux sauvegardent. La seconde sauvegarde ecrase le changement du premier worker. | Les assets generes reviennent silencieusement apres l'execution d'un autre worker |
| Tempetes d'evenements | Une sauvegarde declenche plusieurs subscribers, chacun dispatche des messages, chacun cause plus de sauvegardes | Un import produit genere des milliers de sauvegardes inutiles |
| Explosion des versions | Chaque sauvegarde worker cree une version dont personne n'a besoin | Des milliers de versions par produit, stockage consomme, historique inutile |
| Pas de propriete des champs | Les modifications de contenu et les ecritures systeme passent par le meme chemin save() | L'import ERP ecrase les champs soigneusement rediges |
| Pas de controle des effets de bord | Version::disable() est un flag statique global, pas scope ni composable | Desactiver les versions dans un worker affecte tous les workers du meme processus |
Avant qu'on corrige ces problemes, un import produit prenait des heures et generait des files de messages massives. Apres la refonte de l'architecture, le meme import s'execute en minutes avec des effets de bord controles et previsibles.
Le modele d'etat en trois couches
La decision architecturale centrale : separer trois preoccupations que Pimcore fusionne en une seule.
┌─────────────────────────────────────────────────────────┐
│ │
│ Layer 1: OPERATIONAL WORKFLOW (human process) │
│ ┌─────┐ ┌───────────┐ ┌──────────┐ ┌──────────┐ │
│ │ NEW │─▶│IN_PROGRESS│─▶│IN_REVIEW │─▶│ APPROVED │ │
│ └─────┘ └───────────┘ └──────────┘ └────┬─────┘ │
│ ▲ │ │ │
│ └────────────┘ │ │
│ (feedback loop) ▼ │
│ ┌───────────┐ │
│ │ PUBLISHED │ │
│ └─────┬─────┘ │
│ │
├────────────────────────────────────────────────────────┤
│ │
│ Layer 2: PUBLICATION STATE (Pimcore built-in) │
│ published = true → product is live on website │
│ published = false → not visible on any channel │
│ Draft versions → edits saved without publishing │
│ │
├────────────────────────────────────────────────────────┤
│ │
│ Layer 3: CHANNEL ELIGIBILITY (computed, NOT stored) │
│ isChannelReady = published=true │
│ AND workflow=PUBLISHED │
│ AND ChannelValidator.passes() │
│ AND not archived │
│ │
└─────────────────────────────────────────────────────────┘
Couche 1 : Workflow operationnel
Un seul workflow sur la classe Product via l'integration Symfony Workflow de Pimcore. Type : state_machine (un seul etat a la fois).
Ce workflow repond a : Qui possede le produit en ce moment ? Dans quelle phase est-il ? Qui agit ensuite ?
pimcore:
workflows:
product_lifecycle:
enabled: true
label: 'Product Lifecycle'
type: 'state_machine'
supports:
- 'Pimcore\Model\DataObject\Product'
initial_markings:
- 'new'
marking_store:
type: state_table
places:
new:
label: 'New'
color: '#90CAF9'
permissions:
- save: true
publish: false
in_progress:
label: 'In Progress'
color: '#FFE082'
permissions:
- save: true
publish: false
in_review:
label: 'In Review'
color: '#FFAB91'
approved:
label: 'Approved'
color: '#A5D6A7'
published:
label: 'Published'
color: '#4CAF50'
archived:
label: 'Archived'
color: '#BDBDBD'
La distinction cle que la plupart des equipes ratent : il n'y a pas d'etat REJECTED. Le rejet est une transition retour vers IN_PROGRESS avec un commentaire obligatoire stocke dans Notes & Events. Cela garde le workflow propre et le processus de revue comme une boucle, pas un cul-de-sac.
Couche 2 : Etat de publication
Ce n'est PAS un workflow. Cela utilise les mecanismes existants de Pimcore :
published = truecontrole la visibilite sur le site web- Le versioning Pimcore cree des snapshots a chaque sauvegarde
- Les versions brouillon permettent aux editeurs de travailler sans affecter le site en production
- La publication promeut une version specifique comme version live
Cela donne un comportement similaire a Git :
| Concept Git | Equivalent Pimcore |
|---|---|
Branche main | Version actuellement publiee |
| Feature branch | Version brouillon (sauvegardee sans publication) |
| Merge to main | Action de publication (promeut le brouillon en live) |
| Historique de commits | Historique des versions dans l'onglet Versions |
Quand un editeur sauvegarde sans publier, seule une version brouillon est creee. Les tables publiees restent inchangees. Le site web en production ne voit jamais du travail a moitie termine.
Couche 3 : Eligibilite par canal (calculee, pas stockee)
C'est la decision qui a elimine toute une classe de bugs. L'eligibilite par canal (si un produit est eligible pour un canal de sortie specifique comme un flux marketplace, un pipeline d'export, ou une API partenaire) n'est PAS un champ stocke sur le produit. Elle est calculee a partir de la verite courante.
class ProductOutputEligibility
{
public function isChannelReady(Product $product, string $channel): bool
{
return $product->isPublished()
&& $this->workflowState->getCurrentState($product) === 'published'
&& !$this->workflowState->isArchived($product)
&& $this->channelValidator->isValid($product, $channel);
}
public function getBlockingErrors(Product $product, string $channel): array
{
$errors = [];
if (!$product->isPublished()) {
$errors[] = 'Product must be published';
}
// ... verifier l'etat du workflow, l'archivage
return array_merge($errors, $this->channelValidator->getErrors($product, $channel));
}
}
Pourquoi le calcul est meilleur qu'un champ de statut stocke :
| Champ stocke | Resultat calcule |
|---|---|
| Peut devenir obsolete (indique READY mais l'image requise a ete supprimee) | Reflete toujours la verite courante |
| Necessite une reinitialisation manuelle apres les changements | Pas de reinitialisation necessaire, calcule a la demande |
| Doit etre synchronise avec l'etat du workflow | Pas de synchronisation necessaire |
| Cree une duplication de la verite | Source unique de verite : les donnees reelles |
| Necessite une migration pour les nouvelles regles | Il suffit de mettre a jour la logique du validateur |
L'ancien systeme utilisait des hacks ou les produits devaient etre depublies pour les preparer pour certains canaux. Cela cassait la visibilite du site web a chaque fois. L'approche calculee elimine completement ce pattern.
Pour plus de details sur notre approche des pipelines d'ingenierie de donnees et de la sortie specifique par canal, cette page de service couvre notre approche globale.
Propriete des champs : Qui peut ecrire quoi
La deuxieme decision architecturale critique : tous les champs ne sont pas egaux. Certains appartiennent aux editeurs, certains aux machines, certains aux deux avec des regles.
pimtx:
field_ownership:
Product:
editor_owned:
- name
- description
- shortDescription
- images
system_owned:
- thumbnail
- searchIndex
- checksum
- lastSyncTimestamp
shared:
- categories
- price
- availability
- status
| Domaine | Proprietaire | Exemples | Chemin de mutation |
|---|---|---|---|
| Editeur | Utilisateurs admin | nom, description, images | Save natif Pimcore |
| Systeme | Workers et integrations | miniatures, index de recherche, checksums | Couche transactionnelle |
| Partage | Les deux, avec politique de conflit | categories, prix, disponibilite | Couche transactionnelle avec strategie de conflit |
La propriete des champs determine :
- Quels champs declenchent la detection de changement pour quelles operations
- Quelles strategies de resolution de conflits s'appliquent
- Si la mise a jour partielle est sure pour un champ donne
- Ce qui apparait dans la vue audit metier vs technique
Sans propriete des champs, un import ERP peut ecraser du contenu soigneusement redige. Avec elle, l'import ne touche que les champs qui lui appartiennent, et les champs partages utilisent une strategie de conflit configuree (retry, skip, fail, ou merge-if-safe).
Ce pattern est central dans la facon dont nous avons construit PimTx, notre couche transactionnelle et de concurrence open source pour Pimcore. L'equipe consulting a aide plusieurs clients entreprise Pimcore a implementer exactement ce pattern.
Controle des Event Subscribers : Stopper la cascade
Le pattern le plus dangereux dans les systemes Pimcore entreprise est la cascade de sauvegardes. Une sauvegarde declenche plusieurs event subscribers. Chacun dispatche des messages asynchrones. Chaque message handler charge le produit, modifie un champ, et sauvegarde. Chaque sauvegarde declenche a nouveau tous les subscribers.
L'EventSubscriberSupervisor est un singleton scope au processus qui controle quels subscribers sont actifs :
// Desactiver tous les event subscribers applicatifs avant la sauvegarde worker
$this->eventSubscriberSupervisor->disableAll();
try {
$product->setQrCode($generatedAsset);
$product->save();
} finally {
$this->eventSubscriberSupervisor->enableAll();
}
L'ordre des operations est crucial. Se tromper cree exactement la boucle que tu essaies d'empecher :
// MAUVAIS : les evenements sont reactives AVANT le save
$this->eventSubscriberSupervisor->disableAll();
try {
// effectuer le travail...
} finally {
$this->eventSubscriberSupervisor->enableAll(); // reactive ici
}
$product->save(); // le save declenche les evenements, la boucle demarre
// CORRECT : le save a lieu DANS le scope desactive
$this->eventSubscriberSupervisor->disableAll();
try {
$product->setQrCode($generatedAsset);
$product->save(); // save ici, evenements supprimes
} finally {
$this->eventSubscriberSupervisor->enableAll();
}
C'est scope au processus. Cela ne desactive les subscribers que dans le meme processus PHP. Les autres pods worker ont leurs propres instances du superviseur. Mais puisque le save ne dispatche pas de nouveaux messages (les subscribers sont desactives), aucun nouveau message n'atteint les autres workers.
Gestion des versions : Empecher l'explosion
Dans le systeme d'origine, chaque sauvegarde worker creait une version. Avec 6 workers traitant chaque changement produit, une seule modification humaine generait 6+ versions dont personne n'avait besoin. Au fil du temps, les produits accumulaient des milliers de versions, consommant du stockage et rendant l'historique des versions inutile pour un veritable audit.
La solution : un version guard scope qui supprime les versions inutiles pendant les operations systeme.
// PimTx scoped version guard (reference-counted)
$versionGuard = $this->versionGuardFactory->create();
$versionGuard->suppress();
try {
// Operations systeme multiples, aucune version creee
$product->setThumbnail($thumbnailAsset);
$product->save();
$product->setChecksum($newChecksum);
$product->save();
} finally {
$versionGuard->restore();
}
Contrairement au Version::disable() global de Pimcore, ce guard est compte par reference et scope. Les operations imbriquees fonctionnent correctement. Un guard qui se restore ne reactive pas accidentellement les versions pour une operation parente qui a encore besoin de les supprimer.
| Approche | Scope | Imbrication | Securite |
|---|---|---|---|
Version::disable() (Pimcore) | Statique global | Cassee (tout enable() reactive pour tout le monde) | Dangereux en workers concurrents |
| Scoped Version Guard (PimTx) | Par operation, compte par reference | Correct (restore seulement quand tous les guards sont liberes) | Sur pour les workers concurrents |
Le resultat : les sauvegardes editeur creent des versions (piste d'audit preservee). Les sauvegardes worker creent des entrees de log d'operation (observabilite complete sans gonflement des versions). Tu peux voir exactement ce que chaque worker a fait, quand, et sur quels champs, sans defiler a travers 4 000 entrees de version inutiles.
Securite des imports ERP
La partie la plus politiquement sensible de toute architecture PIM : que se passe-t-il quand l'ERP pousse des donnees.
Dans le systeme d'origine, les imports ERP ecrasaient tout. Descriptions soigneusement redigees, categories definies avec soin, statut editorial. Tout disparu apres un import nocturne.
La solution architecturale combine la propriete des champs avec des regles specifiques a l'import :
# ERP import field mapping
# Champs PROTEGES (pas dans le mapping, l'import ne peut pas les toucher) :
# - description (propriete editeur)
# - shortDescription (propriete editeur)
# - images (propriete editeur)
# - workflow state (controle par le processus)
# Champs IMPORTES (propriete ERP) :
# - erpId (cle de resolution)
# - sku
# - dimensions
# - weight
# - ean
# Champs PARTAGES (l'import met a jour, mais la detection de changement s'applique) :
# - categories (strategie de merge)
# - price (ecrasement avec notification)
# - availability (ecrasement avec verification d'impact)
Quand un import ERP modifie un champ critique pour le metier sur un produit publie, la detection d'impact signale automatiquement le produit pour revue. L'import n'a pas besoin de connaitre les workflows editoriaux. Le systeme de propriete des champs s'en charge.
Gardes-fous critiques :
- L'eligibilite par canal est recalculee automatiquement (calculee, pas stockee)
- L'etat du workflow n'est jamais reinitialise par les imports
- Les champs propriete de l'editeur ne sont pas dans le mapping d'import
- Les champs partages utilisent des strategies de conflit avec notification
- L'EventSubscriberSupervisor empeche les cascades declenchees par l'import
Que se passe-t-il quand un produit en production est modifie
C'est le flux le plus critique cote utilisateur. Un editeur doit mettre a jour un produit en production sans casser le site web ni aucun canal de sortie.
1. Product is in PUBLISHED state, published=true, live on website
2. Editor opens product, modifies description
3. Editor clicks "Save" (not "Publish")
4. Pimcore creates a DRAFT VERSION only
5. Published tables stay unchanged
6. Website continues serving the current published version
7. Change-impact detection runs:
- If business-critical fields changed: relevant teams notified
- If only internal/SEO fields changed: no notification
8. Editor continues working on the draft
9. When ready: submit for review (IN_REVIEW)
10. Reviewer approves: transition to APPROVED
11. Release manager publishes: draft promoted to live
12. Workflow returns to PUBLISHED
13. Channel eligibility recalculates automatically
Le site web ne voit jamais du travail a moitie termine. Aucun canal de sortie n'est casse par des changements en cours. Tout est versionne, auditable et reversible.
C'est exactement le type d'architecture logicielle sur mesure que nous construisons pour les clients entreprise. Si tu as besoin d'aide pour planifier une refonte de workflow, demande un devis ou contacte notre equipe consulting.
Detection d'impact des changements
Tous les changements ne se valent pas. Un editeur qui corrige une faute de frappe dans le texte SEO ne devrait pas declencher une revue de canal. Un editeur qui remplace l'image principale du produit, si.
Le systeme de detection de changement classifie les modifications par impact :
class ChangeImpactClassifier
{
private const BUSINESS_CRITICAL_FIELDS = [
'description',
'shortDescription',
'images',
'technicalAttributes', // Classification Store
'price',
'availability',
'categories',
];
private const NON_IMPACTFUL_FIELDS = [
'seoText',
'searchKeywords',
'internalTags',
'lastSyncTimestamp',
];
public function classify(Product $product, array $changedFields): ChangeImpact
{
$critical = array_intersect($changedFields, self::BUSINESS_CRITICAL_FIELDS);
if (count($critical) > 0) {
return ChangeImpact::BUSINESS_CRITICAL;
}
$nonImpactful = array_intersect($changedFields, self::NON_IMPACTFUL_FIELDS);
if (count($nonImpactful) === count($changedFields)) {
return ChangeImpact::NON_IMPACTFUL;
}
return ChangeImpact::STANDARD;
}
}
Implementation : un subscriber PRE_UPDATE charge les donnees de la version precedente, compare champ par champ avec l'etat courant, classifie les changements par impact metier, et stocke le resume des changements en tant que Note sur l'objet.
Regles de validation pour l'eligibilite par canal
Puisque l'eligibilite par canal est calculee, le validateur definit ce que "pret" signifie pour chaque canal :
class ChannelValidator
{
public function isValid(Product $product, string $channel): bool
{
return count($this->getErrors($product, $channel)) === 0;
}
public function getErrors(Product $product, string $channel): array
{
$errors = [];
// Exigences communes a tous les canaux
if (!$product->getMainImage()) {
$errors[] = 'At least one product image required';
}
if (empty($product->getDescription())) {
$errors[] = 'Description text required in at least one locale';
}
// Exigences specifiques au canal
if ($channel === 'marketplace') {
if (empty($product->getPrice())) {
$errors[] = 'Price is required for marketplace export';
}
if (empty($product->getCategories())) {
$errors[] = 'At least one category required for marketplace';
}
}
return $errors;
}
}
L'interface montre exactement ce qui bloque l'eligibilite pour chaque canal. Pas de devinettes, pas de "demande au responsable du canal." Le produit passe la validation ou le systeme te dit pourquoi il ne la passe pas.
Pour voir comment nous gerons des patterns de validation similaires dans la conception de workflows IA et la gouvernance IA, ces guides couvrent les paralleles.
La couche transactionnelle (PimTx)
Tous ces patterns convergent dans PimTx, la couche transactionnelle et de concurrence que nous avons construite sous forme de bundle Symfony. Chaque ecriture systeme devient une operation explicite :
// Au lieu du raw $product->save()
$result = $this->transactionManager->execute(
OperationContext::for($product)
->name('qr_code_generation')
->systemField('qrCode')
->lock(LockType::OPERATION)
->version(VersionPolicy::SUPPRESS_PIMCORE_VERSION)
->events(EventPolicy::SUPPRESS)
->conflict(ConflictStrategy::RETRY)
->maxRetries(3)
->idempotencyKey("qr:{$product->getId()}:{$locale}")
->mutate(function (Product $p) use ($qrAsset) {
$p->setQrCode($qrAsset);
})
);
if ($result->wasSkipped()) {
// Idempotent : la meme operation a deja tourne
$this->logger->info('QR generation skipped', [
'reason' => $result->skipReason,
'product_id' => $product->getId(),
]);
}
Ce que cette declaration fait :
- Acquiert un lock scope a l'operation (empeche la generation concurrente de QR codes pour le meme produit)
- Verifie l'idempotence (la meme operation avec la meme cle ne tournera pas deux fois)
- Supprime la creation de version (l'operation est logguee dans l'audit PimTx, pas dans les versions Pimcore)
- Supprime les event subscribers (empeche les sauvegardes en cascade)
- Retry en cas de conflit (si un autre worker a modifie le produit entre le load et le save)
- Retourne un resultat structure (succes, skip, conflit resolu, ou echec)
La regle de gouvernance : toute mutation non-editeur qui atteint Pimcore via un save() non gere est consideree hors politique. Le code systeme doit passer par la couche transactionnelle. Sans cette regle, les equipes contournent progressivement la couche et recreent les memes incidents.
Pour en savoir plus sur la facon dont nous observons et monitorons des systemes comme celui-ci en production, consulte notre guide d'observabilite IA, qui couvre des patterns similaires de logging structure et de tracing.
Architecture de notifications
Le workflow de Pimcore supporte les notifications sur les transitions :
| Evenement | Qui est notifie | Canal |
|---|---|---|
| Produit entre en IN_REVIEW | Role reviewer | Notification Pimcore + email |
| Produit approuve | Proprietaire du produit / editeur | Notification Pimcore |
| Changement critique metier detecte | Equipes de canal concernees | Email avec resume des changements |
| Produit publie modifie (brouillon cree) | Editeur responsable | Notification Pimcore |
| Produit publie | Release manager | Notification Pimcore |
| Import modifie des champs partages | Proprietaire du champ | Email avec diff |
Les notifications portent du contexte : ce qui a change, qui l'a change, quels champs ont ete affectes, et le niveau d'impact metier. Pas juste "Le produit 12345 a ete mis a jour."
Pieges courants
-
Utiliser plusieurs workflows. Un seul workflow par classe de produit. Les workflows multiples creent des conflits d'etat et de la confusion dans les permissions. L'eligibilite par canal est geree par le calcul, pas par des workflows separes.
-
Stocker le statut de canal comme un champ. Tout champ de statut stocke devient obsolete des que quelqu'un supprime une image ou modifie un attribut requis. Calcule l'eligibilite a partir de la verite courante.
-
Ignorer la propriete des champs. Sans propriete des champs, chaque import, worker et editeur se bat pour les memes champs via le meme chemin
save(). Definis qui possede quoi avant la premiere ligne de code. -
Utiliser
Version::disable()globalement. Ce flag statique global casse quand plusieurs operations tournent en concurrence. Utilise des version guards scopes et comptes par reference. -
Laisser les imports toucher l'etat du workflow. Les imports ERP doivent mettre a jour les champs de donnees, pas l'etat du processus. L'etat du workflow est controle par les transitions humaines et la detection automatique de changement.
-
Declencher une revue a chaque changement. Classifie les changements par impact. Les mises a jour de texte SEO ne devraient pas declencher des revues metier. Seuls les changements de champs critiques devraient le faire.
-
Ne pas separer la sauvegarde editoriale de la sauvegarde systeme. La plus grande source de tempetes d'evenements. Les sauvegardes worker et les sauvegardes editeur ont besoin de chemins differents avec des politiques d'effets de bord differentes.
-
Ignorer la boucle de sauvegarde. Un seul subscriber non controle peut transformer un import produit en un desastre de plusieurs heures. L'EventSubscriberSupervisor n'est pas optionnel.
Feuille de route d'implementation
Phase 1 : Fondations (workflow + eligibilite par canal)
- Definir les etats et transitions du workflow en YAML
- Implementer l'eligibilite par canal calculee (remplacer les champs de statut stockes)
- Configurer les permissions du workflow par etat
- Detection d'impact basique (critique metier vs non impactant)
Phase 2 : Gouvernance (propriete des champs + controle des evenements)
- Definir le registre de propriete des champs (editeur/systeme/partage par champ)
- Implementer l'EventSubscriberSupervisor
- Ajouter des version guards scopes pour les operations worker
- Configurer la protection des champs pour l'import ERP
Phase 3 : Production complete (couche transactionnelle + notifications)
- Deployer la couche transactionnelle PimTx
- Ajouter l'idempotence pour toutes les operations worker
- Implementer l'architecture de notifications
- Logging d'audit complet avec vues metier et technique
- Tests de regression sur tous les workers et integrations
Consulte notre presentation de confiance et conformite pour voir comment nous documentons les garanties systeme pour les clients entreprise.
Points cles a retenir
-
Separe trois preoccupations en trois couches. Le workflow controle le processus. Le flag published controle la visibilite web. L'eligibilite par canal est calculee a partir de la verite courante. Les melanger cree des hacks qui cassent tout.
-
La propriete des champs n'est pas optionnelle a l'echelle. Sans elle, chaque worker, import et editeur ecrase le travail des autres via le meme chemin
save(). Definis qui possede quels champs avant d'ecrire la premiere transition de workflow. -
Le controle des event subscribers empeche les desastres en cascade. Une seule sauvegarde non controlee peut declencher des milliers de messages. L'EventSubscriberSupervisor est le correctif le plus impactant pour la performance de Pimcore a l'echelle.
-
Calcule, ne stocke pas l'eligibilite par canal. Tout champ de statut stocke devient obsolete. Calcule l'eligibilite a partir de l'etat publie courant, de l'etat du workflow et des regles de validation. Pas de synchronisation necessaire, pas de donnees obsoletes possible.
-
Les version guards preservent les pistes d'audit sans l'explosion. Les sauvegardes editeur creent des versions. Les sauvegardes worker creent des logs d'operation. Meme observabilite, 1/100eme du stockage.
-
Encapsule Pimcore, ne le forke pas. PimTx gouverne toutes les ecritures systeme via un modele d'operation explicite. Il encapsule
$object->save()avec des guards. Il ne remplace ni n'ecrase le core de Pimcore. Les mises a jour restent propres.
Nous avons construit PimTx comme un bundle Symfony open source pour exactement ces patterns. Si tu fais tourner une installation Pimcore entreprise et que tu rencontres ces problemes de scaling, nos services IA et d'ingenierie de donnees couvrent toute la stack, de la revue d'architecture au deploiement en production.
Pret a reconcevoir ton architecture de workflows Pimcore ? Contacte notre equipe ou demande un devis.
Sujets couverts
Guides connexes
Guide Entreprise des Systèmes d'IA Agentiques
Guide technique des systemes d'IA agentiques en entreprise. Decouvre l'architecture, les capacites et les applications des agents IA autonomes.
Lire le guideCommerce Agentique : Comment laisser les agents IA acheter en toute securite
Comment concevoir un commerce agentique gouverne. Moteurs de politiques, portes d'approbation HITL, reçus HMAC, idempotence, isolation multi-tenant et le protocole Agentic Checkout complet.
Lire le guideLes 9 endroits où ton système IA laisse fuir des données (et comment colmater chacun)
Cartographie systématique de chaque point de fuite de données dans les systèmes IA. Prompts, embeddings, logs, appels d'outils, mémoire d'agent, messages d'erreur, cache, données de fine-tuning et transferts entre agents.
Lire le guidePrêt à construire des systèmes IA prêts pour la production ?
Notre équipe est spécialisée dans les systèmes IA prêts pour la production. Discutons de comment nous pouvons aider.
Démarrer une conversation