Skip to content

fix: Don't refresh all cart leafs on every article write - #188

Draft
sveneberth wants to merge 2 commits into
viur-framework:mainfrom
sveneberth:fix/cart-article-update-level
Draft

fix: Don't refresh all cart leafs on every article write#188
sveneberth wants to merge 2 commits into
viur-framework:mainfrom
sveneberth:fix/cart-article-update-level

Conversation

@sveneberth

Copy link
Copy Markdown
Member

Opened as draft because this is a deliberate behaviour change of the relation semantics — please discuss.

Problem

CartItemSkel.article uses the default updateLevel of RelationalBone, which is RelationalUpdateLevel.Always. Consequence: every write of an article spawns an update_relations task that refreshes every cart_leaf referencing that article — including years-old abandoned session baskets.

In a production system with frequent article imports this:

Why the refresh is not needed

  • The shop_* refKeys of the relation are a snapshot taken when the article is put into the cart (copy_article_values) — the skeleton itself documents them as "Bones to store a frozen copy of the article values".
  • The price shown and charged is always computed live via the price bone (ComputeMethod.AlwaysPricearticle_skel_full, which reads the full article entity, not the refKeys).
  • Frozen (ordered) carts must not change at all (see fix: Respect is_frozen in cart computes and mutation paths #185).

So the automatic relation refresh performs work that has no effect on what customers see or pay.

Solution

Set updateLevel=RelationalUpdateLevel.OnValueAssignment on CartItemSkel.article; the refKeys snapshot is then only written when the relation itself is (re)assigned. Docstring on the bone explains the reasoning.

Impact to discuss

Projects that read the article.dest.shop_* refKeys of open carts directly (instead of the leaf's own shop_* copies or the price bone) would no longer see article changes reflected automatically. If that is a supported use case, an alternative would be a targeted refresh of only active carts — but the default of refreshing every historic leaf on every article write seems clearly unintended.

🤖 Generated with Claude Code

`CartItemSkel.article` used the default `updateLevel`
(`RelationalUpdateLevel.Always`): every write of an article spawned an
`update_relations` task that refreshes *every* cart leaf referencing
it -- including years-old abandoned baskets. With frequent article
imports this floods the task queue and, combined with broken tree data,
produced endlessly retried tasks.

The refresh has no user-visible effect: the `shop_*` refKeys are a
snapshot taken when the article is put into the cart, and current
prices are always computed live via the `price` bone. Use
`RelationalUpdateLevel.OnValueAssignment` instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@sveneberth sveneberth added Priority: Medium This issue may be useful, and needs some attention. bug(fix) Something isn't working or address a specific issue or vulnerability discussion component: skeleton performance labels Jul 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug(fix) Something isn't working or address a specific issue or vulnerability component: skeleton discussion performance Priority: Medium This issue may be useful, and needs some attention.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant