Ctrl K
ComunidadGuías…

electron/cloud-space.mjs

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// Room on the person's Cloud for what goes there: whether it fits now, fits once its volume grows (the Admin's grow, in
// steps of its own), or never fits on this plan. The one-time move measures before it sends files and attachments.
const SPACE_MARGIN = 256 * 1024 ** 2;
const GB = 1024 ** 3;
/** Must match openmaus-cloud's VOLUME_EXTEND step. */
const DISK_STEP_GB = 10;
const count = (value) => Number.isSafeInteger(value) && value >= 0;

/** `copies`: how many times the bytes take room there while they arrive (a whole-workspace copy needs three). */
export function moveFit({ localBytes, freeBytes, uploadReceived = 0, volumeBytes = null, disk = null, copies = 3 }) {
  const neededBytes = copies * localBytes + SPACE_MARGIN, available = freeBytes + uploadReceived;
  const maxBytes = count(disk?.maxBytes) && disk.maxBytes > 0 ? disk.maxBytes : null;
  const volume = [volumeBytes, disk?.volumeBytes, disk?.startBytes].find(value => count(value) && value > 0) ?? null;
  if (available >= neededBytes) return { fit: "now", neededBytes, freeBytes: available };
  const room = maxBytes && volume && maxBytes > volume ? maxBytes - volume : 0;
  if (room > 0 && available + room >= neededBytes) {
    const sizeGb = Math.min(Math.floor(maxBytes / GB), Math.ceil((volume + neededBytes - available) / GB / DISK_STEP_GB) * DISK_STEP_GB);
    return { fit: "grow", neededBytes, freeBytes: available, maxBytes, sizeGb };
  }
  return { fit: "never", neededBytes, freeBytes: available, ...(maxBytes ? { maxBytes, ...(disk?.largest === true ? { largest: true } : {}) } : volume ? { volumeBytes: volume } : {}) };
}

/** Has the Admin grow the volume to `fit.sizeGb`, then waits until `free()` reports the room: "grown", or why not. */
export async function growToFit(fit, { grow, free, sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)), pollMs = 2_000, timeoutMs = 5 * 60_000, now = Date.now }) {
  let answer = null;
  try { answer = await grow(fit.sizeGb); } catch { return "unavailable"; }
  if (!answer?.supported) return "unsupported";
  if (answer.refused) return "full";
  for (const deadline = now() + timeoutMs; now() <= deadline; await sleep(pollMs)) {
    const bytes = await free().catch(() => null);
    if (Number.isFinite(bytes) && bytes >= fit.neededBytes) return "grown";
  }
  return "unavailable";
}