const { DataApi } = require("@unity-services/cloud-save-1.4");
module.exports = async ({ params, context, logger }) => {
const { projectId } = context;
const levelId = String(params.levelId);
const cloudSave = new DataApi(context);
const COLLECTION = "level-stats";
const KEY = "level-completion";
const MAX_RETRIES = 5;
const BASE_DELAY_MS = 50;
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
try {
const read = await cloudSave.getPrivateCustomItems(projectId, COLLECTION, [KEY]);
const record = read.data.results[0] ?? { value: {}, metadata: {} };
const stats = record.value;
const old = stats[levelId]?.NumCompletions || 0;
const updated = old + 1;
stats[levelId] = { NumCompletions: updated };
await cloudSave.setPrivateCustomItemBatch(projectId, COLLECTION, {
data: [{
key: KEY,
value: stats,
writeLock: record.metadata?.etag
}]
});
return { NumCompletions: updated };
} catch (err) {
if (err.response?.status === 412 && attempt < MAX_RETRIES) {
const backoff = BASE_DELAY_MS * 2 ** (attempt - 1) + Math.random() * BASE_DELAY_MS;
logger.warn(`ETag conflict (try ${attempt}/${MAX_RETRIES}) – retrying in ${Math.round(backoff)} ms`);
await new Promise(r => setTimeout(r, backoff));
continue;
}
logger.error("IncrementNumCompletion failed", { message: err.message });
throw err;
}
}
throw new Error(`Failed to increment after ${MAX_RETRIES} retries`);
};