@mpgd/adapter-devvit 0.9.12 → 0.9.13
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.
|
@@ -35,8 +35,10 @@ function normalizeDevvitOrder(input, expectedStatus) {
|
|
|
35
35
|
}
|
|
36
36
|
const product = requireRecord(record.products[0], 'Devvit payment product');
|
|
37
37
|
const orderId = requireString(record.id, 'order.id');
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
// The order must carry the purchasing user so the server-side binding to the
|
|
39
|
+
// authenticated context is always enforced; an order without userId cannot be
|
|
40
|
+
// attributed and must not be fulfilled or refunded.
|
|
41
|
+
if (requireString(record.userId, 'order.userId') !== playerId) {
|
|
40
42
|
throw new TypeError('Devvit payment order userId must match the authenticated context playerId.');
|
|
41
43
|
}
|
|
42
44
|
const platformSku = requireString(product.sku, 'order.products[0].sku');
|
|
@@ -98,17 +98,26 @@ async function mutateIfValue(input) {
|
|
|
98
98
|
}
|
|
99
99
|
await transaction.multi();
|
|
100
100
|
multiStarted = true;
|
|
101
|
-
|
|
101
|
+
const counting = countQueuedCommands(transaction);
|
|
102
|
+
await input.queueMutation(counting.transaction);
|
|
103
|
+
if (counting.count() === 0) {
|
|
104
|
+
throw new Error('Devvit Redis transaction queued no commands before EXEC.');
|
|
105
|
+
}
|
|
102
106
|
const results = await transaction.exec();
|
|
107
|
+
// `@devvit/redis` `TxClient.exec()` never resolves `null`: it maps the
|
|
108
|
+
// server reply to an array, so an aborted WATCH transaction surfaces as
|
|
109
|
+
// an empty array. Fewer results than queued commands is a conflict; `null`
|
|
110
|
+
// stays a conflict for clients that follow the classic Redis contract.
|
|
103
111
|
if (results === null) {
|
|
104
112
|
continue;
|
|
105
113
|
}
|
|
106
114
|
if (!Array.isArray(results)) {
|
|
107
115
|
throw new Error('Devvit Redis transaction returned an unsupported response.');
|
|
108
116
|
}
|
|
109
|
-
if (results.length
|
|
110
|
-
|
|
117
|
+
if (results.length < counting.count()) {
|
|
118
|
+
continue;
|
|
111
119
|
}
|
|
120
|
+
return true;
|
|
112
121
|
}
|
|
113
122
|
catch (error) {
|
|
114
123
|
await bestEffortReset(transaction, multiStarted);
|
|
@@ -117,6 +126,33 @@ async function mutateIfValue(input) {
|
|
|
117
126
|
}
|
|
118
127
|
throw new Error(`Devvit Redis transaction contention exceeded ${String(input.transactionAttempts)} attempts for key: ${input.key}`);
|
|
119
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* Wraps a transaction so the number of commands queued after MULTI is known
|
|
131
|
+
* when EXEC resolves, which is what distinguishes a completed transaction from
|
|
132
|
+
* an aborted one on the Devvit Redis client.
|
|
133
|
+
*/
|
|
134
|
+
function countQueuedCommands(transaction) {
|
|
135
|
+
let queued = 0;
|
|
136
|
+
return {
|
|
137
|
+
count: () => queued,
|
|
138
|
+
transaction: {
|
|
139
|
+
multi: () => transaction.multi(),
|
|
140
|
+
discard: () => transaction.discard(),
|
|
141
|
+
exec: () => transaction.exec(),
|
|
142
|
+
unwatch: () => transaction.unwatch(),
|
|
143
|
+
async set(key, value, options) {
|
|
144
|
+
const result = await transaction.set(key, value, options);
|
|
145
|
+
queued += 1;
|
|
146
|
+
return result;
|
|
147
|
+
},
|
|
148
|
+
async del(...keys) {
|
|
149
|
+
const result = await transaction.del(...keys);
|
|
150
|
+
queued += 1;
|
|
151
|
+
return result;
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
}
|
|
120
156
|
async function bestEffortReset(transaction, multiStarted) {
|
|
121
157
|
try {
|
|
122
158
|
if (multiStarted) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mpgd/adapter-devvit",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.13",
|
|
4
4
|
"description": "Reddit Devvit Web platform adapter for mpgd games.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"dependencies": {
|
|
57
57
|
"@devvit/web": "0.14.1",
|
|
58
58
|
"@mpgd/bridge": "0.10.0",
|
|
59
|
-
"@mpgd/game-services": "0.17.
|
|
59
|
+
"@mpgd/game-services": "0.17.1",
|
|
60
60
|
"@mpgd/platform": "0.14.0"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|