`pipe` support
ttyS15 opened this issue · comments
Alexey Manaev commented
There are needs to run several task as one batch (may be as atomic action).
Requested by @bourivouh
Alexey Manaev commented
@bourivouh, есть идея как это сделать и вроде без сложных заморочек.
# Клиент
from celery_rpc.client import Client()
c = Client()
# Создаётся прокси-билдер, который внутри держит ссылку на c
p = c.pipe(atomic=True)
# Компанует во внутренней структуре данных о цепочке задач. Аналогично Model.objects.filter().order_by()[:].
# Для конструирования комманд есть метод Client.prepare_task()
p = p.filter(...).update(...)
p = p.delete(...)
# Выполняет отправку через клиент с.request(c.PIPE_TASK, data), где дата - данные о задачах
r = p.send()
# Тем временем на сервере
@task(bind=True)
def pipe(data, atomic=False):
context_manager = atomic_commit_on_success if atomic else FakeAtomic
result = []
with context_manager:
for task, args, kwargs in data:
t = self.app.tasks[task]
r.append(t.apply(*args, **kwargs)
return result
Нет желания запилить? ;)
Timur Kozhevnikov commented
Возможен ли такой кейс?
- Создать объект A,
- Создать объект Б другой модели с FK на объект 1,
- Выполнить call c ID объекта 2?
И все в рамках одной транзакции.
По логике такой кейс будет очень тяжелый если первым идет например p.filter() с 100500 записями. Хотя... в рамках одного процесса это будет ссылка на уже имеющийся объект.
И как узнать у второй задачи что куда подставлять от первой, если только:
p.filter('modelA', status=active).create('modelB', title='haha', st_fk='{values[0].pk}').call('func', obj_id='{values.pk}')
Alexey Manaev commented
Хотелось бы сюда добавить что-то такое: