@blamejs/blamejs-shop 0.4.61 → 0.4.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/lib/asset-manifest.json +1 -1
- package/lib/cart-bulk-ops.js +15 -4
- package/lib/customer-impersonation.js +26 -3
- package/lib/customer-merge.js +109 -28
- package/lib/operator-approvals.js +16 -2
- package/lib/order-exchanges.js +49 -18
- package/lib/payment-retries.js +35 -0
- package/lib/pick-lists.js +60 -22
- package/lib/plan-changes.js +21 -2
- package/lib/preorder.js +163 -40
- package/lib/print-queue.js +18 -2
- package/lib/purchase-orders.js +131 -36
- package/lib/seller-signup.js +37 -6
- package/lib/split-shipments.js +57 -16
- package/lib/suggestion-box.js +35 -2
- package/package.json +1 -1
package/lib/suggestion-box.js
CHANGED
|
@@ -754,11 +754,44 @@ function create(opts) {
|
|
|
754
754
|
var ts = _now();
|
|
755
755
|
var srcVotes = Number(src.vote_count) || 0;
|
|
756
756
|
|
|
757
|
-
|
|
757
|
+
// Atomic claim: flip the source to 'duplicate' under a WHERE that
|
|
758
|
+
// re-asserts the JS preconditions (not already a duplicate, not
|
|
759
|
+
// archived). SQLite/D1 serializes writers, so this conditional
|
|
760
|
+
// UPDATE is the exactly-once gate — two concurrent linkers both
|
|
761
|
+
// pass the read-time checks above, but only one wins this claim.
|
|
762
|
+
// The loser (rowCount === 0) did NOT transition the row, so it
|
|
763
|
+
// must NOT migrate votes a second time (which would double-count
|
|
764
|
+
// srcVotes onto the canonical); it returns the already-linked row.
|
|
765
|
+
var claim = await query(
|
|
758
766
|
"UPDATE suggestions SET status = 'duplicate', canonical_id = ?1, " +
|
|
759
|
-
"vote_count = 0, updated_at = ?2
|
|
767
|
+
"vote_count = 0, updated_at = ?2 " +
|
|
768
|
+
"WHERE id = ?3 AND status <> 'duplicate' AND archived_at IS NULL",
|
|
760
769
|
[cid, ts, sid],
|
|
761
770
|
);
|
|
771
|
+
if (Number(claim.rowCount || 0) !== 1) {
|
|
772
|
+
// Lost the race (a concurrent linkDuplicates already flipped the
|
|
773
|
+
// source) — or it was archived between the read and the claim.
|
|
774
|
+
// Re-read to distinguish: a row now in 'duplicate' is the
|
|
775
|
+
// expected concurrent-link outcome, so return it idempotently;
|
|
776
|
+
// anything else means the precondition genuinely no longer holds.
|
|
777
|
+
var current = await _getRaw(sid);
|
|
778
|
+
if (current && current.status === "duplicate") {
|
|
779
|
+
return {
|
|
780
|
+
suggestion_id: sid,
|
|
781
|
+
canonical_id: current.canonical_id,
|
|
782
|
+
migrated_votes: 0,
|
|
783
|
+
source: _decode(current),
|
|
784
|
+
canonical: _decode(await _getRaw(current.canonical_id)),
|
|
785
|
+
};
|
|
786
|
+
}
|
|
787
|
+
var lost = new Error("suggestionBox.linkDuplicates: source could not be claimed for linking");
|
|
788
|
+
lost.code = "SUGGESTION_ALREADY_DUPLICATE";
|
|
789
|
+
throw lost;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
// Only the claim winner reaches here — migrate the source's net
|
|
793
|
+
// vote_count (captured from the row this claim transitioned) onto
|
|
794
|
+
// the canonical exactly once.
|
|
762
795
|
if (srcVotes !== 0) {
|
|
763
796
|
await query(
|
|
764
797
|
"UPDATE suggestions SET vote_count = vote_count + ?1, updated_at = ?2 WHERE id = ?3",
|
package/package.json
CHANGED