Giter Club home page Giter Club logo

fast_bitrix24's People

Contributors

leshchenko1979 avatar miron95 avatar msitetop avatar whiteapfel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fast_bitrix24's Issues

Стратегия выборки в get_all()

Текущая стратегия выборки в get_all() с использованием параметра start, хотя и позволяет использовать параллелизм, но замедляет работу сервера. Ее применение может быть неоптимальным при условиях:

  1. требуется сложная фильтрация с выгрузкой небольшого количества записей
  2. полный список сущностей (без фильтров) содержит большое количество записей

Для таких случаев более оптимальной может быть стратегия, описанная тут:
https://dev.1c-bitrix.ru/rest_help/rest_sum/start.php

Можно дать пользователю в get_all() параметр strategy, который он будет использовать, чтобы выбрать стратегию. Либо можно после первого вызова в зависимости от размера параметра filter в params и от total, возвращаемого в первом ответе, выбирать стратегию автоматически. Алгоритм выбора стратегии можно подобрать опытным путем.

Ошибка в примерах

В примере https://github.com/leshchenko1979/fast_bitrix24#%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5
deals = b.get_all('crm.deal.get', params={
'select': ['', 'UF_'],
'filter': {'CLOSED': 'N'}
})
Выдает ошибку, т.к. метод crm.deal.get ожидает id в параметрах.
Если заменить метод crm.deal.get на crm.deal.list, то пример отрабатывает, как и ожидается.

Что, если в call() был передан batch, и запустился autobatch?

  • Очевидно, что в таких случаях нужно отключать автобатчевание. Также, если было передано несколько батчей списком, нужно отключать упаковку в батчи, но список выполнять параллельно.
  • Описать в доке, что при подаче списка батчей порядок выполнения не гарантирован

details -> params

В доке Битрикса используется термин "параметры".

Сортировка результатов

Сейчас сложно писать куски кода, где предполагается определенный порядок элементов в возвращаемом списке.

Например, по get_all() предполагается, что элементы отсортированы по ID, а по get_by_ID и call, что порядок элементов в результатах вызова такой же, как и во входных массивах.

Однако есть развилки:

get_all()

  • А мы уверены, что в каждом списке будет ID? Или, более общо, элемент, по которому будет сортировка? Как нам понять, есть он или нет?

Решение:

- [ ] Если есть ID, то сортировать по нему. Если его нет, то не сортировать. - решил, что в этом нет потребности. Сортировка потребует конверсии ID в int, а это может быть неожиданным для пользователя.

get_by_ID()

  • Что возвращать?
    • dict вида ID: results?
      • сломается имеющийся код
      • но поиск в результатах вызова будет очень прост
    • tuple вида (ID, results), где tuple отсортирован по ID?
      • код не сломается
    • просто список списков результатов, отсортированный также, как и входящий список
      • код сломается
      • поиск в результатах вызова также будет прост
      • кажется, что список списков - это менее понятно, чем dict
      • будет хорошая аналогия со структурой результатов, возвращаемых методом call()

Решение:

  • Пока что сортировать текущий list of tuples
    • Оказалось, что в этом нет смысла, пока в _get_by_ID на входе происходит дедупликация списка ID через преобразование его в set.
      • [х] Нужно выбрать один из вариантов:
        • при получении дублей на вход поднимать исключение,
        • не обращать внимание на дубли и делать запросы столько раз, сколько запросил пользователь - отличная идея для начала, так как она убирает неожиданное для пользователя поведение
          • Убрать дедупликацию ID_list на входе
          • Сортировать результаты согласно порядок элементов в ID_list
        • отказаться от идеи сортировки списка результатов
          • в том числе, путем #45

call()

  • Если сортировать результаты так же, как и запросы, то как это сделать через код?

  • Надо сделать preserve_IDs, на место IDs подавать номер элемента item_list. Потом по этому номеру делать сопоставление результатов в выходном массиве.

  • Поправить всю доку касательно сортировки

Задержка между батчами - "горшочек, не вари"

Попытка создать более 2500 лидов за один вызов call() вызывает 500 Internal server error. Задержка в 5 сек. между такими вызовами позволяет обходить эту проблему.

  • Сделать в Bitrix.__init__ параметр requests_per_second, который будет оверрайдить умолчание в 2 сек. и будет публичным (то есть, пользователь сможет его менять между вызовами, если ему предстоят тяжелые вызовы на создание объектов).

ServerRequestHandler.run()

Метод берет на вход корутину, которую оборачивает в код, который оборачивает вызов этой корутины в:

  • asyncio.run()
  • async with self:

Будет вызываться из реаизацийUserRequestAbsract.run().

call() vs get_all()

Почему нельзя везде использовать call()? Чем get_all() лучше?

Рефакторинг slow()

slow перенести в класс Bitrix / ServerResponseHandler - это даст возможность запускать одновременно несколько экземпляров класса Bitrix, решить проблему несовместимости с асинхронными вызовами и правильно наладит инкапсуляцию.

Перейти на dict в результатах get_by_ID()

Сейчас get_by_ID возвращает list of tuples вида

[
    (ID_1, result_1),
    (ID_2, result_2),
    (ID_3, result_3),
    ...
]

Кажется, было бы гораздо проще, если бы он возвращал dict вида

{
    ID_1: result_1,
    ID_2: result_2,
    ID_3: result_3,
    ...
}

Это бы упростило некоторые операции с результатами вызова этого метода:

  1. Когда нужно отбросить айдишники и оставить только массив результатов:
  • сейчас:
[single_result for ID, single_result in get_by_ID_results]
  • после перехода на dict:
get_by_ID_results.values()
  1. Когда в результатах нужно найти конкретный ID:
  • сейчас:
[single_result for ID, single_result in get_by_ID_results 
 if ID == ID_to_look_for][0]
  • после перехода на dict:
get_by_ID_results[ID_to_look_for]

в get_by_ID() добавить параметр "ID_field_name"

Тогда внутри метода при формировании запросов будет использоваться не метка "ID", а метка ID_field_name.

Пример - когда нужно выгрузить дела по сделке (метод crm.activity.get), то отборочным признаком является не ID, а OWNER_ID.

Ожидаем, что сервер Битрикса будет возвращать dict после выполнения батча, а он возвращает list

Что вызывает исключения в текущем коде.

В частности, list возвращается вместо dict при попытке вызвать crm.deal.get со списком ID.

  • Построить больше тестов, проверяющих формат возвращаемых сервером данных в results
  • Соответствующим образом адаптировать _request_list

Рефакторинг

https://app.genmymodel.com/api/repository/leshchenko/fast-bitrix24

  • UserRequest и производные
  • SingleServerRequest
  • MultipleServerRequest и проивзодные
  • Весь метод _request_list перенести в абстрактный класс, который будет содержать шаблонный метод, который будет обращаться к методам, переопределяемым в конкретных классах

slow() не работает

Текущий алгоритм при поступлении нескольких одновременных запросов ждем по всем по ним параллельно, а должен ждать последовательно. Нужно использовать asyncio.lock().

  • Написать тесты на slow()

get_all() не работает с параметром limit()

Выдаёт больше лимита, что вполне объяснимо, так как алгоритм get_all() не анализирует наличие лимита в params, а только ориентируется на total в ответах сервера.

  • Можно сделать параметр отдельный параметр limit, который можно будет вызывать как при обращении к get_all(), так и в 'params'.
  • Метод должен конструировать запросы к серверу таким образом, чтобы вовремя остановиться.
  • Опасность представляет возможный возврат дублей сервером при отсутствии сортировки. в параметрах запроса

Может, сделать один мегаметод для регулировки pool_size, requests_per_second и cautious_mode?

Потому что если ты подаешь список, который сильно нагружает сервер, то уменьшение скорости запросов не сильно спасет - тебе надо бы еще и забыть о пуле запросов.

  • Что если сделать context wrapper Bitrix.slow(), внутри которого можно задать свой pool_size и requests_per_second?
  • Убрать кастомные параметры из __init__?
  • Убрать настройку autobatch и везде соответственно подчистить код, убрав if self._autobatch:

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.