const { DataApi } = require("@unity-services/cloud-save-1.4"); module.exports = async ({ params, context, logger }) => { const { projectId } = context; const totalLevels = Number(params.totalLevels); if (!Number.isInteger(totalLevels) || totalLevels < 1) { throw new Error("Parameter 'totalLevels' must be a positive integer."); } const cloudSave = new DataApi(context); const COLLECTION = "level-stats"; const KEY = "level-completion"; const MAX_RETRIES = 5; const BASE_DELAY = 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 statsObj = record.value; const etag = record.metadata?.etag; let created = 0; for (let lvl = 0; lvl <= totalLevels - 1; lvl++) { if (!statsObj[lvl]) { statsObj[lvl] = { NumCompletions: 0 }; created++; } } if (created === 0) { return { Initialized: 0, AlreadyPresent: totalLevels }; } await cloudSave.setPrivateCustomItemBatch(projectId, COLLECTION, { data: [{ key: KEY, value: statsObj, writeLock: etag }] }); return { Initialized: created, AlreadyPresent: totalLevels - created }; } catch (err) { if (err.response?.status === 412 && attempt < MAX_RETRIES) { const backoff = BASE_DELAY * 2 ** (attempt - 1) + Math.random() * BASE_DELAY; logger.warn(`ETag conflict, retry ${attempt}/${MAX_RETRIES} in ${Math.round(backoff)} ms`); await new Promise(r => setTimeout(r, backoff)); continue; } logger.error("InitAllLevelStats failed", { message: err.message }); throw err; } } throw new Error(`Failed after ${MAX_RETRIES} retries`); };