From eb3393f1b8c2e677d5e637ea0ca832cba7b88114 Mon Sep 17 00:00:00 2001 From: Padreug Date: Sun, 3 May 2026 09:16:21 +0200 Subject: [PATCH] fix(market): re-link stallName when stall arrives after product MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Subscription delivers stall (kind 30017) and product (kind 30018) events without ordering guarantees. handleProductEvent and loadProducts looked up stall name once at product-ingest time and froze "Unknown Stall" on the product object when the stall hadn't arrived yet — even when the stall landed milliseconds later. Two-sided fix in the Pinia store: - addStall: after upserting a stall, sweep products and re-stamp stallName for any matching stall_id (handles product-arrives-first race + downstream stall name updates). - addProduct: do the lookup itself instead of trusting the caller's stallName field (handles stall-arrives-first race + paranoia). Both paths converge on the live stalls collection, so eventual consistency is guaranteed regardless of event order. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/modules/market/stores/market.ts | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/modules/market/stores/market.ts b/src/modules/market/stores/market.ts index b1a11ba..7c0d8b1 100644 --- a/src/modules/market/stores/market.ts +++ b/src/modules/market/stores/market.ts @@ -239,14 +239,23 @@ export const useMarketStore = defineStore('market', () => { } const addProduct = (product: Product) => { - const existingIndex = products.value.findIndex(p => p.id === product.id) + // Lookup stallName from the current stall set — the value passed in by + // the caller can be stale ("Unknown Stall") if the stall event hadn't + // arrived yet. The reverse race (stall arrives first) is handled in + // addStall below. + const matchedStall = stalls.value.find(s => s.id === product.stall_id) + const enriched: Product = matchedStall + ? { ...product, stallName: matchedStall.name } + : product + + const existingIndex = products.value.findIndex(p => p.id === enriched.id) if (existingIndex >= 0) { - products.value[existingIndex] = product + products.value[existingIndex] = enriched } else { - products.value.push(product) + products.value.push(enriched) } } - + const addStall = (stall: Stall) => { const existingIndex = stalls.value.findIndex(s => s.id === stall.id) if (existingIndex >= 0) { @@ -254,6 +263,14 @@ export const useMarketStore = defineStore('market', () => { } else { stalls.value.push(stall) } + // Re-stamp stallName on any products that arrived before this stall did + // (or whose stall name has changed). Direct property mutation on items + // in a reactive array triggers Vue's deep reactivity. + products.value.forEach(p => { + if (p.stall_id === stall.id && p.stallName !== stall.name) { + p.stallName = stall.name + } + }) } const addMarket = (market: Market) => {