Ошибка журнала облачных функций Firebase Ошибка: Процесс завершен с кодом 16 и Ошибка: 4 DEADLINE_EXCEDED: Превышен крайний срок

# #javascript #firebase #google-cloud-firestore #google-cloud-functions

Вопрос:

В последнее время я регулярно сталкиваюсь с ошибками в своих облачных функциях firebase. Особенно это функция планировщика, которая запускается каждые 30 минут для обновления данных в магазине firestore.

Мой код выглядит так:

 exports.updateRiverLevelsData = functions  .runWith({ timeoutSeconds: 540, memory: "1GB" })  .pubsub.schedule("every 30 minutes")  .onRun(async (context) =gt; {  const scotlandResponse = await axios.get(  "https://www.riverapp.net/affiliate/api/get_stations?providerId=559ba5cd84821f077403c4b8"  );  const irelandResponse = await axios.get(  "https://www.riverapp.net/affiliate/api/get_stations?providerId=580e616584821f5ed78e9ee7"  );  const walesResponse = await axios.get(  "https://www.riverapp.net/affiliate/api/get_stations?providerId=5e4c4c5650ac9c863f897ca3"  );  // const englandResponse = await axios.get(  // "https://www.riverapp.net/affiliate/api/get_stations?providerId=54aaf0a7e4b01337250b209d"  // );  const scotland = await scotlandResponse.data;  const ireland = await irelandResponse.data;  const wales = await walesResponse.data;  // const england = await englandResponse.data;   return await Promise.all([  // insertLevels(england, "england"),  insertLevels(scotland, "scotland"),  insertLevels(ireland, "ireland"),  insertLevels(wales, "wales"),  ]);  });  exports.updateRiverLevelsDataEngland = functions  .runWith({ timeoutSeconds: 540, memory: "1GB" })  .pubsub.schedule("every 30 minutes")  .onRun(async (context) =gt; {  const englandResponse = await axios.get(  "https://www.riverapp.net/affiliate/api/get_stations?providerId=54aaf0a7e4b01337250b209d"  );  const england = await englandResponse.data;   return await insertLevels(england, "england");  });  const insertLevels = async (country: any, label: string) =gt; {  const db = admin.firestore();  interface ISomeObject {  [key: string]: any;  }  const legends: ISomeObject = {};  const gaugeLegends: ISomeObject = {};  try {  for (let i = 0; i lt; country.length; i  ) {  let refRiver = country[i].riverName;  if (refRiver.includes("/")) {  refRiver = refRiver.replace("/", "-");  }  if (!legends[refRiver]) {  legends[refRiver] = {  gauges: [  {  gaugename: country[i].gaugeName,  lastupdate: new Date(country[i].latestLevelTime).toISOString(),  levelseries: [`${country[i].latestLevelValue}`],  leveltrend: "",  pin: false,  rivername: refRiver,  temptrend: "",  timeseries: [new Date().toISOString()],  tempseries: [`${country[i].latestTemperatureValue}`],  },  ],  };  } else {  const temp = legends[refRiver];  const newObj = {  gaugename: country[i].gaugeName,  lastupdate: new Date(country[i].latestLevelTime).toISOString(),  levelseries: [`${country[i].latestLevelValue}`],  leveltrend: "",  pin: false,  rivername: refRiver,  temptrend: "",  timeseries: [new Date().toISOString()],  tempseries: [`${country[i].latestTemperatureValue}`],  };  temp.gauges.push(newObj);  legends[refRiver] = temp;  }  }  country.map((item: { gaugeName: string | number }) =gt; {  if (!gaugeLegends[item.gaugeName]) {  gaugeLegends[item.gaugeName] = item;  }  });  const date = new Date(); // 2009-11-10  const dateKey = date.toLocaleString("default", {  month: "long",  year: "numeric",  });   const refCollection = db.collection("riverStoreLevels").doc(dateKey);  const checkData = await refCollection.collection(label).limit(1).get();  if (checkData.size) {  const snapshot = await refCollection.collection(label).get();  const data = await snapshot.docs.map((doc) =gt; {  return {  id: doc.id,  ...doc.data(),  };  });  data.map((item: any) =gt; {  let riverName = item.id;  if (riverName.includes("/")) {  riverName = riverName.replace("/", "-");  }  const gauges = item.gauges;  if (legends[riverName]) {  for (let i = 0; i lt; gauges.length; i  ) {  // cari yang sama dengan data yang baru dan lama  const oldEachGauge = gauges[i];  const newEachGauge = gaugeLegends[oldEachGauge.gaugename];  if (newEachGauge) {  const levelseries = oldEachGauge.levelseries;  const tempseries = oldEachGauge.tempseries;  const timeseries = oldEachGauge.timeseries;  let temptrend = "";  let leveltrend = "";  const latestriverupdate = new Date(  newEachGauge.latestLevelTime  ).toISOString();  if (  parseFloat(levelseries[levelseries.length - 1]) lt;  parseFloat(newEachGauge.latestLevelValue)  ) {  leveltrend = "raising";  } else if (  parseFloat(levelseries[levelseries.length - 1]) gt;  parseFloat(newEachGauge.latestLevelValue)  ) {  leveltrend = "falling";  } else {  leveltrend = "static";  }   if (  parseFloat(tempseries[tempseries.length - 1]) lt;  parseFloat(newEachGauge.latestTemperatureValue)  ) {  temptrend = "raising";  } else if (  parseFloat(tempseries[tempseries.length - 1]) gt;  parseFloat(newEachGauge.latestTemperatureValue)  ) {  temptrend = "falling";  } else {  temptrend = "static";  }   levelseries.push(newEachGauge.latestLevelValue.toString());  tempseries.push(newEachGauge.latestTemperatureValue.toString());  timeseries.push(new Date().toISOString());  oldEachGauge.leveltrend = leveltrend;  oldEachGauge.temptrend = temptrend;  oldEachGauge.lastupdate = latestriverupdate;  }  }  legends[item.id] = { gauges: item.gauges };  }  });  const batchArray: any[] = [];  batchArray.push(db.batch());  let operationCounter = 0;  let batchIndex = 0;  for (const [key, value] of Object.entries(legends)) {  let refRiver = key;  if (refRiver.includes("/")) {  refRiver = refRiver.replace("/", "-");  }  const docRef = refCollection.collection(label).doc(refRiver);  batchArray[batchIndex].set(docRef, value);  operationCounter  ;   if (operationCounter === 499) {  batchArray.push(db.batch());  batchIndex  ;  operationCounter = 0;  }  }  batchArray.forEach(async (batch) =gt; await batch.commit());  return;  } else {  console.log("Document Not Exist");  const batchArray: any[] = [];  batchArray.push(db.batch());  let operationCounter = 0;  let batchIndex = 0;   for (const [key, value] of Object.entries(legends)) {  let refRiver = key;  if (refRiver.includes("/")) {  refRiver = refRiver.replace("/", "-");  }  const docRef = refCollection.collection(label).doc(refRiver);  batchArray[batchIndex].set(docRef, value);  operationCounter  ;   if (operationCounter === 499) {  batchArray.push(db.batch());  batchIndex  ;  operationCounter = 0;  }  }  batchArray.forEach(async (batch) =gt; await batch.commit());  return;  }  } catch (err) {  const e = (err as Error).message;  functions.logger.error(e);  return;  } };  

функция работает нормально, но иногда не все документы обновляются должным образом, и в журнале всегда появляются ошибки

 Error: Process exited with code 16  Error: 4 DEADLINE_EXCEEDED: Deadline exceeded  

Я знаю, что первая ошибка означает что-то вроде уже отправленных заголовков, но я не могу понять, в чем проблема с моей функцией. Я также знаю, что для firebase существуют некоторые ограничения на запись, но функция в основном просто обновляет поля массива документов для каждого документа в каждой коллекции.

Структура базы данных: Уровни реки (коллекция) -gt; Дата.сейчас() (документ) -gt;gt; Англия (коллекция) -gt;gt;gt; тест (документ) -gt;gt;gt;gt; тест.данные().датчики (поле, которое будет обновлено)