Arhn - архитектура программирования

Транзакции Firestore запускаются несколько раз, что приводит к неверным данным

Итак, у меня есть облачная функция, которая запускается каждый раз, когда транзакция нравится / не нравится. Эта функция увеличивает / уменьшает LikeCount. Я использовал транзакции firestore, чтобы добиться того же. Я думаю, проблема в том, что код внутри блока транзакции выполняется несколько раз, что может быть правильным в соответствии с документацией.

Но мой счетчик лайков иногда обновляется некорректно.

 return firestore.runTransaction(function (transaction) {
        return transaction.get(transRef).then(function (transDoc) {
            let currentLikesCount = transDoc.get("likesCount");
            if (event.data && !event.data.previous) {
                newLikesCount = currentLikesCount == 0 || isNaN(currentLikesCount) ? 1 : transDoc.get("likesCount") + 1;
            } else {
                newLikesCount = currentLikesCount == 0 || isNaN(currentLikesCount) ? 0 : transDoc.get("likesCount") - 1;
            }
            transaction.update(transRef, { likesCount: newLikesCount });
        });
    });

У кого-нибудь был подобный опыт


  • But my Likes count are being updated incorrectly at certain times. - не могли бы вы подробнее рассказать, когда наступают эти определенные времена и при каких обстоятельствах? 13.02.2018
  • это нерегулярно и происходит случайно. Должен ли я вернуть transaction.update (transRef, {likeCount: newLikesCount}); ? 13.02.2018
  • Вы используете событие записи Firestore для запуска облачной функции? Пока Firestore находится в стадии бета-тестирования, его поведение триггера имеет некоторые ограничения. См. Этот ответ: stackoverflow.com/q/48735862/4815718 13.02.2018
  • @BobSnyder. Это ограничитель шоу. У нас не может быть просто идемпотентных функций. Правильно? Любые сведения о том, когда эти услуги будут стабильными 13.02.2018
  • Я не знаю, когда (и если) ограничения будут сняты. Вы можете обратиться в службу поддержки Firebase 13.02.2018

Ответы:


1

Ребята наконец выяснили причину такого неожиданного поведения.

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

Многие приложения реального времени имеют документы, которые действуют как счетчики. Например, вы можете подсчитывать «лайки» для публикации или «избранное» для определенного элемента.

В Cloud Firestore вы можете обновлять один документ примерно раз в секунду, что может быть слишком мало для некоторых приложений с высоким трафиком.

https://cloud.google.com/firestore/docs/solutions/counters

Меня не убедил такой подход, поскольку он слишком сложен для простого случая использования, когда я наткнулся на следующий блог

https://medium.com/evenbit/on-collision-course-with-cloud-firestore-7af26242bc2d

Эти ребята использовали комбинацию Firestore + Firebase, тем самым устранив свои слабые места.

Cloud Firestore удобно расположен рядом с базой данных Firebase Realtime, и они легко доступны для использования, смешивания и сопоставления в приложении. Вы можете свободно хранить данные в обоих местах для своего проекта, если это соответствует вашим потребностям.

Итак, почему бы не использовать базу данных Realtime для одной из ее сильных сторон: для управления быстрыми потоками данных от распределенных клиентов. Это единственная проблема, которая возникает при попытке агрегировать и подсчитывать данные в Firestore.

Неправильно говорить, что Firestore - это обновление базы данных Realtime (как она рекламируется), но это другая база данных с разными целями, и обе могут и должны сосуществовать в крупномасштабном приложении. Это моя мысль.

14.02.2018
  • как это рекламируется. У вас есть ссылка на это? Firestore не оплачивается как обновление RTDB. Если вы видели это в официальных документах Google, я хотел бы знать. См. Сравнения здесь и здесь. 14.02.2018
  • Cloud Firestore - это новая флагманская база данных Firebase для разработки мобильных приложений. Он улучшает успехи базы данных реального времени за счет новой, более интуитивной модели данных. Cloud Firestore также предлагает более насыщенные и быстрые запросы и лучше масштабируется, чем база данных в реальном времени. firebase.google.com/docs/firestore/rtdb-vs-firestore. Как он масштабируется, когда он даже не может обрабатывать записи, подобные RTDB 15.02.2018
  • В той же статье объясняются преимущества каждого из них. Не видно, что это обновление где-то там, извините. Он, безусловно, пытается улучшить ограничения RTDB, как и любой последующий продукт, уделяя гораздо больше внимания избыточности и надежности, жертвуя некоторыми микросекундами скорости и небольшой долей простоты. Все разумные сравнения. 17.02.2018
  • @SharanMohandas Так вы имеете в виду, что ограничение на обновление документа не применимо к базе данных в реальном времени? Какова допустимая максимальная скорость записи для RTDB? 03.06.2020

  • 2

    Это может иметь какое-то отношение к тому, что вы возвращаете из функции, так как у вас

    return transaction.get(transRef).then(function (transDoc) { ... })
    

    И затем еще один возврат внутри этого обратного вызова, но не return внутри самого внутреннего вложенного обратного вызова. Так что, возможно, он не выполняет transaction.update. Попробуйте удалить первые два return ключевых слова и добавить одно перед transaction.update:

    firestore.runTransaction(function (transaction) {
            transaction.get(transRef).then(function (transDoc) {
                let currentLikesCount = transDoc.get("likesCount");
                if (event.data && !event.data.previous) {
                    newLikesCount = currentLikesCount == 0 || isNaN(currentLikesCount) ? 1 : transDoc.get("likesCount") + 1;
                } else {
                    newLikesCount = currentLikesCount == 0 || isNaN(currentLikesCount) ? 0 : transDoc.get("likesCount") - 1;
                }
                return transaction.update(transRef, { likesCount: newLikesCount });
            });
        });
    
    13.02.2018
  • Поскольку это асинхронная облачная функция, я должен вернуть обещание, чтобы отметить завершение. См. Ниже firebase.google.com/docs/functions/terminate-functions Использование Эти рекомендуемые подходы к управлению жизненным циклом ваших функций: Разрешить функции, которые выполняют асинхронную обработку (также известную как фоновые функции), возвращая обещание JavaScript. 13.02.2018
  • Да, ты прав, я пропустил эту часть. Так что в этом случае, возможно, вам просто нужно избавиться от одного из первых двух операторов return, которые у вас были (без добавления другого перед transaction.update 13.02.2018
  • Меня беспокоит то, что неправильное срабатывание вашей функции затрудняет определение основной причины. Знаете ли вы, происходит ли это только тогда, когда транзакция получает много лайков / антипатий в течение короткого периода времени, например 5 дизлайков и 8 лайков в течение 2 секунд? Я бы попытался создать несколько тестовых примеров, чтобы увидеть, сможете ли вы воспроизвести это неправильное количество обновлений на постоянной основе. 13.02.2018
  • Я тоже так думаю. Необходимо знать, как функция выполняется одновременно 13.02.2018

  • 3

    Тайм-ауты

    Прежде всего, проверьте журналы облачных функций, чтобы узнать, есть ли у вас timeout сообщения.

    Function execution took 60087 ms, finished with status: 'timeout'
    

    Если да, отсортируйте свою функцию так, чтобы она возвращала Promise.resolve(). И показывает

    Function execution took 344 ms, finished with status: 'ok'
    

    Идемпотентность

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

    См. этот пример, чтобы убедиться, что функции запускаются только один раз.

    13.02.2018
  • Функции заканчиваются статусом «ОК» в течение 5000 мс. 14.02.2018
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..