// From syncIdempotent()
// Logic: Batching requests to respect API limits & prevent duplicates
function syncIdempotent(sheetName, tableId, uniqueFieldName) {
// 1. Fetch all existing Airtable records to build a Lookup Map
const existingRecords = fetchAllAirtableRecords(tableId);
const recordMap = new Map();
existingRecords.forEach(r => recordMap.set(r.fields[uniqueFieldName], r.id));
// 2. Diff Local Data vs Remote Data
const {hdr, data} = read(sheetName);
const toInsert = [];
const toUpdate = [];
data.forEach((row) => {
const uniqueVal = row[uniqueColIndex];
const fields = mapRowToFields(row);
if (recordMap.has(uniqueVal)) {
toUpdate.push({ id: recordMap.get(uniqueVal), fields: fields });
} else {
toInsert.push({ fields: fields });
}
});
// 3. Execute Batched API Calls (Max 10 per request)
while (toInsert.length > 0) {
const batch = toInsert.splice(0, 10);
airtablePOST(tableId, { records: batch });
Utilities.sleep(250); // Rate limit backoff
}
}