leshchenko1979 / fast_bitrix24 Goto Github PK
View Code? Open in Web Editor NEWВысокопроизводительный API wrapper для Питона для быстрого массового обмена данными с Битрикс24 через REST API
License: MIT License
Высокопроизводительный API wrapper для Питона для быстрого массового обмена данными с Битрикс24 через REST API
License: MIT License
Текущая стратегия выборки в get_all()
с использованием параметра start
, хотя и позволяет использовать параллелизм, но замедляет работу сервера. Ее применение может быть неоптимальным при условиях:
Для таких случаев более оптимальной может быть стратегия, описанная тут:
https://dev.1c-bitrix.ru/rest_help/rest_sum/start.php
Можно дать пользователю в get_all()
параметр strategy
, который он будет использовать, чтобы выбрать стратегию. Либо можно после первого вызова в зависимости от размера параметра filter
в params
и от total
, возвращаемого в первом ответе, выбирать стратегию автоматически. Алгоритм выбора стратегии можно подобрать опытным путем.
Возможно, сериализация результатов и сравнение их таким образом будет быстрее перебора ID.
"сохранение токенов разных порталов в базе для быстрой реализации полноценных приложений." - https://dev.bitrix24.ru/company/personal/user/9863/blog/4151/?commentId=19047#com19047
В примере 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, то пример отрабатывает, как и ожидается.
В доке Битрикса используется термин "параметры".
params
-- dictselect
(list of str)order
filter
limit
start
Официальное PHP API Битрикс использует название метода callMethod
Сейчас сложно писать куски кода, где предполагается определенный порядок элементов в возвращаемом списке.
Например, по get_all()
предполагается, что элементы отсортированы по ID, а по get_by_ID
и call
, что порядок элементов в результатах вызова такой же, как и во входных массивах.
Однако есть развилки:
Решение:
- [ ] Если есть ID, то сортировать по нему. Если его нет, то не сортировать. - решил, что в этом нет потребности. Сортировка потребует конверсии ID в int, а это может быть неожиданным для пользователя.
call()
Решение:
_get_by_ID
на входе происходит дедупликация списка ID через преобразование его в set
.
ID_list
на входеID_list
Если сортировать результаты так же, как и запросы, то как это сделать через код?
Надо сделать preserve_IDs, на место IDs подавать номер элемента item_list. Потом по этому номеру делать сопоставление результатов в выходном массиве.
Поправить всю доку касательно сортировки
Попытка создать более 2500 лидов за один вызов call()
вызывает 500 Internal server error
. Задержка в 5 сек. между такими вызовами позволяет обходить эту проблему.
Bitrix.__init__
параметр requests_per_second
, который будет оверрайдить умолчание в 2 сек. и будет публичным (то есть, пользователь сможет его менять между вызовами, если ему предстоят тяжелые вызовы на создание объектов).Метод берет на вход корутину, которую оборачивает в код, который оборачивает вызов этой корутины в:
asyncio.run()
async with self:
Будет вызываться из реаизацийUserRequestAbsract.run()
.
Почему нельзя везде использовать call()
? Чем get_all()
лучше?
slow
перенести в класс Bitrix
/ ServerResponseHandler
- это даст возможность запускать одновременно несколько экземпляров класса Bitrix
, решить проблему несовместимости с асинхронными вызовами и правильно наладит инкапсуляцию.
Надо :
{ "ID":...,
"fields": {
"TITLE":...
}
}
Иначе иногда сложно понять, какой результат относится к какому ID, особенно если результат не содержит 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,
...
}
Это бы упростило некоторые операции с результатами вызова этого метода:
[single_result for ID, single_result in get_by_ID_results]
get_by_ID_results.values()
[single_result for ID, single_result in get_by_ID_results
if ID == ID_to_look_for][0]
get_by_ID_results[ID_to_look_for]
Тогда внутри метода при формировании запросов будет использоваться не метка "ID"
, а метка ID_field_name
.
Пример - когда нужно выгрузить дела по сделке (метод crm.activity.get
), то отборочным признаком является не ID
, а OWNER_ID
.
Что вызывает исключения в текущем коде.
В частности, list
возвращается вместо dict
при попытке вызвать crm.deal.get
со списком ID.
https://ru.stackoverflow.com/q/1159358/397961
Попытка создать более 2500 лидов за один вызов call() вызывает 500 Internal server error. Задержка в 5 сек. между такими вызовами позволяет обходить эту проблему. Нужно использовать параметр requests_per_second
.
Особенно нужно для тестирования операций с большими сиськами списками.
https://app.genmymodel.com/api/repository/leshchenko/fast-bitrix24
_request_list
перенести в абстрактный класс, который будет содержать шаблонный метод, который будет обращаться к методам, переопределяемым в конкретных классахТеперь, когда есть BatchUserRequest
, из прочих реализаций UserRequestAbstract
можно все почистить.
Все строки - method
и директивы в params
должны пройти через lower()
и strip()
, иначе проверки правильности будут сбоить.
Текущий алгоритм при поступлении нескольких одновременных запросов ждем по всем по ним параллельно, а должен ждать последовательно. Нужно использовать asyncio.lock()
.
Параметр verbose в Bitrix.__init__
Выдаёт больше лимита, что вполне объяснимо, так как алгоритм get_all()
не анализирует наличие лимита в params
, а только ориентируется на total
в ответах сервера.
limit
, который можно будет вызывать как при обращении к get_all()
, так и в 'params'.Проверять, что в параметре вместо списка получен только один элемент, заворачивать его в список, а потом возвращать тоже один элемент вместо списка.
https://stackoverflow.com/questions/1952464/in-python-how-do-i-determine-if-an-object-is-iterable
get_by_ID()
call()
Чтобы следующая команда использовала результаты предыдущей. -- То можно самому сконструировать батч и скормить его в call()
Потому что если ты подаешь список, который сильно нагружает сервер, то уменьшение скорости запросов не сильно спасет - тебе надо бы еще и забыть о пуле запросов.
Bitrix.slow()
, внутри которого можно задать свой pool_size
и requests_per_second
?__init__
?autobatch
и везде соответственно подчистить код, убрав if self._autobatch:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.