# Exercise 2: Resolve Conflicts in an Active-Active Shopping Cart and Profile Store

`ShopWorld` runs active-active in `us-east` and `eu-west` (theory section 2). Both regions accept writes; changes replicate asynchronously in both directions with typical lag of 80–300 ms. Each record carries the region it was last written in and a wall-clock timestamp from that region's servers.

The following concurrent histories were captured from production logs. For each one, you must (a) show what **last-write-wins (LWW)** would produce after both regions sync, (b) say whether that outcome is acceptable, and (c) if not, design the merge rule that should be used instead (theory section 4).

## History 1: Shopping cart

```
t=0      cart(user=42) = { items: [] }                     (both regions)
t=100ms  us-east: add item "SKU-A" qty 1                    (user on phone)
t=140ms  eu-west: add item "SKU-B" qty 2                    (same user on laptop, routed to EU via VPN)
t=400ms  both regions sync
```

## History 2: Shopping cart, remove vs. add

```
t=0      cart(user=42) = { items: [SKU-A x1] }
t=100ms  us-east: remove SKU-A
t=120ms  eu-west: increase SKU-A to qty 3
t=400ms  sync
```

## History 3: Profile display name

```
t=0      profile(user=7).displayName = "Sam"
t=100ms  us-east: displayName = "Samuel"
t=105ms  eu-west: displayName = "Sam K."
t=400ms  sync
```

## History 4: Account balance (store credit)

```
t=0      credit(user=9) = 50.00
t=100ms  us-east: apply refund  +20.00   → writes 70.00
t=110ms  eu-west: redeem credit −30.00   → writes 20.00
t=400ms  sync
```

## History 5: Clock skew

`eu-west`'s clock is 2 seconds **behind** real time.

```
real t=0     profile(user=7).email = "a@x.io"
real t=1.0s  eu-west: email = "b@x.io"   (stamped t=-1.0s because of skew)
real t=1.5s  us-east: email = "c@x.io"   (stamped t=1.5s)
real t=3.0s  eu-west: email = "d@x.io"   (stamped t=1.0s) — the user's LATEST intent
sync
```

## Deliverables

1. For Histories 1–5: the LWW result, whether it's acceptable, and (if not) your replacement rule with the merged result it produces.
2. For History 4, explain why storing the **balance** is the root problem, and redesign the data model so concurrent operations commute (hint: what if each region stores operations or per-region counters instead of a single number?). Show the merged balance under your design.
3. For History 2 (add vs. remove conflict), state the semantics your merge chooses — "add wins" or "remove wins" — and justify the choice from the user's point of view for a shopping cart specifically.
4. For History 5, explain why LWW with wall clocks picked the wrong winner, and name two alternatives (e.g. hybrid logical clocks, version vectors) with one sentence each on what they fix.
5. Finally: which of these records would you **stop writing in both regions at all**, by routing all writes for that record to a single home region (section 4, "avoid the conflict")? Justify with the cost of being wrong.

## Requirements Checklist

- [ ] History 1: LWW loses one item; the correct rule is a set/map union of items (OR-set style), producing both SKU-A and SKU-B.
- [ ] History 2: the answer explicitly picks add-wins or remove-wins and justifies it (most carts choose add-wins — losing an item the user wanted is worse than an extra item they can remove).
- [ ] History 3: LWW (or "show a conflict to the user") is acceptable for a display name — it's a single-valued field where any one of the user's own recent choices is fine.
- [ ] History 4: LWW yields 20.00 or 70.00, both wrong (correct is 40.00); the redesign uses commutative operations (ledger entries or a PN-counter per region), and the merged value is 40.00.
- [ ] History 5: identifies that skewed physical clocks make LWW discard the user's latest write ("d@x.io" loses to "c@x.io"), and mentions HLCs/version vectors or single-region ownership as fixes.
- [ ] Question 5 routes money (store credit) to a single home region per user, and justifies it by the asymmetry of cost: a few hundred ms extra write latency vs. creating or destroying money.
