Fixed/reworked VkTools.get_all_slow_iter method#121
Fixed/reworked VkTools.get_all_slow_iter method#121python273 merged 14 commits intopython273:masterfrom hdk5:get_all_slow_fix
Conversation
|
Накосячил с мержем в свой форк, прошу прощения. К ПРу относятся три последних |
|
Может еще посмотришь execute версию? Думаю там тоже можно count_diff сделать |
|
Посмотрю |
|
Теперь код внутри передаваемой на сервер функции аналогичен тому, что внутри get_all_slow_iter с ограничением на 25 вызовов. |
| var params = %(values)s, | ||
| calls = 0, | ||
| items = [], | ||
| count, new_count, count_diff, response; |
There was a problem hiding this comment.
Может чтобы не копировать логику в python функцию, в аргументы добавить count? Тогда на первом шаге вк функция будет вызываться с count == None, а дальше с count из ответа
There was a problem hiding this comment.
+ offset. Еще можно возвращать need_more с true, если нужно еще раз вызывать вк функцию. Тогда будет:
values['offset'] = 0
count = None
need_more = True
while need_more:
response = ...(..., count=count)
need_more = response['need_more']
values['offset'] = response['offset']
count = response['count']
...
|
Не совсем понимаю, зачем need_more, если всё равно сравнение count и offset должно идти правильно |
|
А вообще, я тут осознала, что если удалить некоторые старые результаты и добавить новые так, что их количество не изменится, то правильность обхода будет всё равно нарушена. Тут уж, если по хорошему, надо смотреть на id у результатов, когда они есть |
|
И ещё, если метод вызвался с одними параметрами в один момент, не значит что в следующую секунду я не попаду в чс/альбом будет удалён/etc. Ух, сколько проблем то. |
| count_diff = new_count - count; | ||
| var response = API.%(method)s(params), | ||
| new_count = response.count, | ||
| count_diff = (count == null : 0 ? new_count - count); |
There was a problem hiding this comment.
разве не something ? iftrue : iffalse?
Ну я имел в виду убрать логику
Хм, мне кажется такое не особо вероятно. Максимум первые X итемов будут не актуальные, но это уже скорее всего будет скравлено в следующие разы (если вообще нужно получать обновления)
Ну тоже не сильно вероятно. В любом случае нужно ловить ошибки при кравлинге |
Оно должно быть в обоих местах. Изменение набора может произойти как в vk-функции (что тоже маловероятно), так и в питоновской функции, пока что-то происходит между yield. |
Но если возвращать последний offset из вк функции и перезаписывать в values, то в python функции count_diff не нужен, не? |
|
Да, точно, теперь понимаю |
|
Там еще предложение есть: #122 |
|
А не получится ли доработать функции так, чтобы была возможность указать, что требуется получать итемы с отрицательным оффсетом: добавить аргумент, за это отвечающий, и исправить сами функции? |
|
То есть, что-то вроде этого: с оффсетом работать как и раньше, к апи обращаться с отрицательным оффсетом, если нужно, заканчивать всё, если ответ пустой |
| count_diff = new_count - (count or new_count) | ||
|
|
||
| if new_count == 0: | ||
| break |
| yield item | ||
|
|
||
| if limit and items_count >= limit: | ||
| if len(response_items) < max_count: |
There was a problem hiding this comment.
if len(items) < max_count:
Вроде при прошлой проверке если бы добавился новый итем, то остановилось бы из-за items = response[key][count_diff:]
|
Отрефакторил, чтобы было проще понять что происходит. Можешь посмотреть все ли ок и я мержну |
|
Но не уверен нужно ли фиксить. Можно начинать с Интересно есть ли у других методов отрицательный offset |
Да, всё так на самом деле |
| ) | ||
|
|
||
| items = response['items'] | ||
| items = response[key] |
There was a problem hiding this comment.
Функция всегда 'items' возвращает
There was a problem hiding this comment.
Ну вроде бы и да, но изначально этот метод принимал ключ как параметр. Сам я сходу не нахожу методов апи, возвращающих массив под каким-то иным именем.
There was a problem hiding this comment.
Где-то было users, но я не про это. Тут вызывается вк функция, она всегда items возвращает. В вк функции используется key
There was a problem hiding this comment.
А, точно, не обратил внимания
| yield item | ||
|
|
||
| if len(response_items) < max_count: | ||
| if len(response_items) < max_count - count_diff: |
There was a problem hiding this comment.
Разве это не должно исправить преждевременный выход?
There was a problem hiding this comment.
Ну там уже проверка response_items вместо items, так что, как я понимаю, не нужно вычитать count_diff
There was a problem hiding this comment.
Да, точно, не обратил внимания
|
^ там выше 2 коммента к коду |
| ri = response.%(key)s.slice(count_diff); | ||
| items = items + ri; | ||
| offset = offset + params.count + count_diff; | ||
| if (ri.length < params.count - count_diff) { |
There was a problem hiding this comment.
Но тогда здесь вычитать count_diff всё же нужно
There was a problem hiding this comment.
Точно, там хотел немного по другому сделать
|
@hdk5 можешь посмотреть все ли ок и мержну |
|
Вроде всё работает как ожидается 👍 |
|
Какое ожидаемое поведения для negative_offset = True, при условии, что выставлен start_message_id > 0 ? r = tools.get_all('messages.getHistory', 200, {'user_id': user_id, 'start_message_id': 5}, negative_offset=True)
print(json.dumps(r, ensure_ascii=False, indent=4))В данном примере возвращаются сообщения с идентификаторами с 1 по 5. |
Получение сообщений от start_message_id (не включительно) до наиболее нового (включительно) |
|
Значит, вероятно, в текущем алгоритме есть ошибка. |
|
Да, действительно. get_all_slow работает правильно, сейчас посмотрю что не так с execute |
| values['count'] = max_count | ||
|
|
||
| items_count = 0 | ||
| offset = 0 |
There was a problem hiding this comment.
offset = max_count if negative_offset else 0|
Алгоритм с exeute по-прежнему работает неверно :) |
Сначала я заметил, что в текущей реализации обрезаются первые max_count результатов. Это исправил в первом коммите.
Затем, мне там же не понравились две вещи:
Так что вторым коммитом идёт моя реализация этого метода