10 подписчиков
Дошёл до реализации курсоров, интересная проблема вылезла, которой не было в прототипе (точнее была, но там я не думал об этом).
Есть возможность вычитать коллекцию целиком: делаешь запрос query(), он тебе возвращает пачку данных и cursorId, с которым идёшь в readQueryCursor(), который возвращает следующую пачку с новым курсором и так пока не прочитаешь всё.
У пачек есть лимит на количество элементов, вроде бы хорошо. Но что если наш запрос может иметь такие аргументы, которые не выбирают ни строки из всей коллекции?
Например, у нас сколько-то миллионов записей, а запрос просит выбрать те, которые существовали в версии X, где записей было всего пять штук (предположим, что индексов для таких запросов у меня нет (хотя и на самом деле нет и не будет, я предполагаю такие юзкейсы, где история будет быстро отмирать, оставляя только актуальную версию)).
Ну и вот мы бежим такие по коллекции и пытаемся собрать пачку из 200 элементов (наш лимит). Долго бежим, а элементов всё нет и нет.
А если клиент ошибся в своих скриптах и прислал нам сотни таких запросов (хотя и десятка хватит)? Можно ввести таймауты, ограничить количество одновременных запросов.
Но теперь я смотрю на это так, что страдать должен клиент, а не база. У API чего-либо не должно существовать методов которые вернут результат «ну как будет готово, так и вернём, может 50мс, может пять минут, может час, мы не знаем». Методы должны всегда отвечать быстро, если же не могут, то говорить «мы приняли ваш заказ, ожидайте» (а затем событием уведомить о готовности).
Второй вариант это усложнение, радикализируем первый. Говорим, что чтение курсора может вернуть... ноль элементов, но если есть идентификатор следующего курсора — там возможно есть что-то ещё. А внутри собираем пачку не только по лимиту элементов, но и считаем, сколько элементов мы уже посмотрели. Если глянули уже, например, тыщ десять, то сворачиваемся, возвращаем что есть, запоминаем в новый курсор место где остановились.
В итоге наш метод ограничен по времени выполнения сверху и будет стабильно возвращать какой-то результат. Что во-первых не требует введения таймаутов (что сложно, т.к. нужно будет потом иногда смотреть, а не отменили ли нашу задачу), во-вторых если нам придёт сотня-тысяча запросов на такие выборки, то мы будем их быстренько разгребать, параллельно обрабатывая и другие запросы, а не всё больше увязать в бесконечных переборах, которые очень быстро забьют все потоки намертво.
#diffbelt
2 минуты
20 декабря 2022