Здесь показаны различия между двумя версиями данной страницы.
Предыдущая версия справа и слева Предыдущая версия Следующая версия | Предыдущая версия | ||
doc:1605:643.mgul.21010-10_13_01 [2024/01/03 17:54] aminaraon [Таблица] |
doc:1605:643.mgul.21010-10_13_01 [2024/01/04 15:05] (текущий) aminaraon [checkDateRangeInRedis(formattedStartDate, formattedEndDate, keysArray)] |
||
---|---|---|---|
Строка 16: | Строка 16: | ||
| //sortRedisKeys(keysArray)// | функция для сортировки массива ключей Redis | | | //sortRedisKeys(keysArray)// | функция для сортировки массива ключей Redis | | ||
| //sortedAndFilteredKeys(formattedStartDate, formattedEndDate)// | асинхронная функция для получения отсортированных и отфильтрованных ключей из Redis | | | //sortedAndFilteredKeys(formattedStartDate, formattedEndDate)// | асинхронная функция для получения отсортированных и отфильтрованных ключей из Redis | | ||
- | | //updateDataInRedis(url)// | асинхронная функция для добавления данных в базу данных Redis | | + | | //updateDataInRedis(url)// | асинхронная функция для добавления данных в Redis | |
| //processAndAggregateLastMeasurements(respondParsed, keysArray)// | функция для обработки данных (для запросов last_measurements) | | | //processAndAggregateLastMeasurements(respondParsed, keysArray)// | функция для обработки данных (для запросов last_measurements) | | ||
| //processAndAggregateResponsesList(respondParsed, keysArray)// | функция для обработки данных (для запросов list) | | | //processAndAggregateResponsesList(respondParsed, keysArray)// | функция для обработки данных (для запросов list) | | ||
Строка 22: | Строка 22: | ||
| //requestAdditionalDataIfMissing(formattedStartDate, formattedEndDate, filteredKeys)// | асинхронная функция для дозапроса данных | | | //requestAdditionalDataIfMissing(formattedStartDate, formattedEndDate, filteredKeys)// | асинхронная функция для дозапроса данных | | ||
| //respondToDataQuery(keys)// | функция предназначена для получения значений по заданным ключам | | | //respondToDataQuery(keys)// | функция предназначена для получения значений по заданным ключам | | ||
- | | **respondToDataQueryParsed(keys)** | функция предназначена для получения значений по заданным ключам | | + | | //respondToDataQueryParsed(keys)// | функция предназначена для получения значений по заданным ключам | |
- | | **applyCalibrationsToData(calibrationData, filteredResponse)** | функция выполняет калибровку данных | | + | | //applyCalibrationsToData(calibrationData, filteredResponse)// | функция выполняет калибровку данных | |
+ | ====== Дополнительные объяснения по функциям ====== | ||
+ | ===== updateDataInRedis(url) ===== | ||
+ | В программе использована конвейерная обработка данных для сведения к минимуму задержек при множественных операциях. Конвейерная обработка в Redis представляет собой метод повышения эффективности, позволяющий одновременно выполнить несколько команд без ожидания ответа на каждую отдельную команду. | ||
+ | ===== | ||
+ | Шаг 1: Получаем ответ от внешнего источника данных | ||
+ | const databaseResponse = await downloadPage(url); | ||
+ | Шаг 2: Получаем массив ключей из ответа | ||
+ | const keys = Object.keys(databaseResponse); | ||
+ | Шаг 3: Объявляем конвейеры для проверки наличия ключей в Redis и добавления данных | ||
+ | const existsPipeline = redis.pipeline(); | ||
+ | const updatePipeline = redis.pipeline(); | ||
+ | Шаг 4: Добавляем команды проверки наличия в Redis для каждого ключа в конвейер | ||
+ | for (const key of keys) { | ||
+ | const currentDate = databaseResponse[key].Date; | ||
+ | existsPipeline.exists(currentDate); | ||
+ | } | ||
+ | Шаг 5: Запускаем конвейер проверки наличия и ждём результат | ||
+ | const existsResults = await existsPipeline.exec(); | ||
+ | Шаг 6: Добавляем данные для отсутствующих ключей | ||
+ | for (let i = 0; i < keys.length; i++) { | ||
+ | const key = keys[i]; | ||
+ | const currentDate = databaseResponse[key].Date; | ||
+ | const keyExistsInRedis = existsResults[i][1] === 1; | ||
+ | if (!keyExistsInRedis) { | ||
+ | const newDataArray = JSON.stringify(databaseResponse[key]); | ||
+ | updatePipeline.set(currentDate, newDataArray, 'EX', REDIS_EXPIRY_SECONDS); | ||
+ | } | ||
+ | } | ||
+ | Шаг 7: Запускаем конвейер добавления данных и ждём результат | ||
+ | await updatePipeline.exec(); | ||
+ | ===== requestAdditionalDataIfMissing(formattedStartDate, formattedEndDate, filteredKeys) ===== | ||
+ | Шаг №1: Инициализация флага для отслеживания обновлений в Redis. | ||
+ | let flag = false; | ||
+ | Шаг №2: Задаем максимальную разницу по времени между записями в секундах | ||
+ | const secondsThreshold = 360; | ||
+ | Шаг №3: Проверяем и добавляем данные, если разница между первым ключом в Redis и начальной датой больше secondsThreshold | ||
+ | const firstKey = filteredKeys[0]; | ||
+ | const formattedFirstKey = moment(firstKey).format(DATE_FORMAT); | ||
+ | const startDifference = moment(formattedFirstKey).diff(moment(formattedStartDate), 'seconds'); | ||
+ | if (Math.abs(startDifference) > secondsThreshold) { | ||
+ | flag = true; | ||
+ | const dataUrl = `${URL_DBROBO}${formattedStartDate}${SDATE_QUERY_PARAM}${formattedFirstKey}`; | ||
+ | await updateDataInRedis(dataUrl); | ||
+ | } | ||
+ | Шаг №4: Проверка и добавление данных для промежуточных ключей | ||
+ | for (let i = 0; i < filteredKeys.length - 2; i++) { | ||
+ | const firstDate = filteredKeys[i]; | ||
+ | const secondDate = filteredKeys[i + 1]; | ||
+ | const formattedFirstDate = moment(firstDate).format(DATE_FORMAT); | ||
+ | const formattedSecondDate = moment(secondDate).format(DATE_FORMAT); | ||
+ | const secondsDifference = moment(formattedSecondDate).diff(moment(formattedFirstDate), 'seconds'); | ||
+ | if (secondsDifference > secondsThreshold) { | ||
+ | flag = true; | ||
+ | const dataUrl = `${URL_DBROBO}${formattedFirstDate}${SDATE_QUERY_PARAM}${formattedSecondDate}`; | ||
+ | await updateDataInRedis(dataUrl); | ||
+ | } | ||
+ | } | ||
+ | Шаг №5: Проверяем и добавляем данные, если разница между последним ключом в Redis и конечной датой больше secondsThreshold | ||
+ | const lastKey = filteredKeys[filteredKeys.length - 1]; | ||
+ | const formattedLastKey = moment(lastKey).format(DATE_FORMAT); | ||
+ | const endDifference = moment(formattedEndDate).diff(moment(formattedLastKey), 'seconds'); | ||
+ | if (Math.abs(endDifference) > secondsThreshold) { | ||
+ | flag = true; | ||
+ | const dataUrl = `${URL_DBROBO}${formattedLastKey}${SDATE_QUERY_PARAM}${formattedEndDate}`; | ||
+ | await updateDataInRedis(dataUrl); | ||
+ | } | ||
+ | Шаг №6: Если флаг установлен в true, возвращение новых отсортированных и отфильтрованных ключей из Redis, иначе возвращаем filteredKeys | ||
+ | return flag ? await sortedAndFilteredKeys(formattedStartDate, formattedEndDate) : filteredKeys; | ||
+ | ===== checkDateRangeInRedis(formattedStartDate, formattedEndDate, keysArray) ===== | ||
+ | Шаг №1: Инициализация переменных, получение начальной и конечной временных меток из Redis | ||
+ | const startDate = keysArray[0]; | ||
+ | const endDate = keysArray[keysArray.length - 1]; | ||
+ | Шаг №2: Расчет временной разницы в минутах между конечной датой Redis и заданной начальной датой. | ||
+ | let startDifference = moment(endDate).diff(moment(formattedStartDate), 'minutes'); | ||
+ | Шаг №3: Проверка, находится ли заданная начальная дата внутри или частично пересекается с временным диапазоном Redis. | ||
+ | if (startDate <= formattedStartDate && formattedStartDate < endDate && Math.abs(startDifference) >= 5) { | ||
+ | // Если условие выполняется, возвращаем true, указывая на пересечение временных диапазонов. | ||
+ | return true; | ||
+ | } | ||
+ | Шаг №4: Расчет временной разницы в минутах между заданной конечной датой массива и начальной датой Redis. | ||
+ | let endDifference = moment(formattedEndDate).diff(moment(startDate), 'minutes'); | ||
+ | Шаг №5: Если ни одно из условий не выполнилось, возвращаем false, указывая на отсутствие пересечения временных диапазонов, иначе true | ||
+ | return formattedStartDate <= startDate && startDate < formattedEndDate && Math.abs(endDifference) >= 5; |