Rethinkdb - строка атомарного извлечения / обновления с определенным условием
У меня есть группа сельдерей, которые должны получить одну запись (строку) из базы данных.
Он должен быть возвращен, только если прошло 60 секунд после поля "last_used", и как только он вернется, он должен обновить "last_used" с текущим временем (чтобы другие работники, которые имеют неограниченные повторы с задержкой 0, не получали то же самое)
Можно ли сделать все это на уровне БД? У меня не было бы другого источника, обновляющего это поле "last_used".
Вот как выглядит один ряд.
{"id": "..." "last_used": "2016-06-31 00:37:21.241833", "item": "string"}
Я старался:
conn = r.connect(host='localhost', port=28015)
do = r.db('database').table('tb').order_by(index=("last_used")).limit(1).update(
{'last_used': r.now()}
, return_changes=True).run(conn)
И это не работает, несколько работников возвращаются в одну строку, прежде чем она будет изменена.
1 ответ
Я думаю, что я сделал это, попытался запустить 50 рабочих против этого с 0 конфликтами. Но я все еще новичок в rethinkdb и хотел бы услышать ваши мысли по этому поводу, заимствованные здесь.
@app.task(bind=True, default_retry_delay=0, max_retries=999)
def ss(self):
conn = r.connect(host='localhost', port=28015)
do = r.db('').table('').order_by("last_used").filter(
r.now() - r.row['last_used'] > 10
).filter({'status': 1}).limit(1).update(
r.branch(r.row["status"] == 1, {'status': 2, "last_used": r.now()}, {}),
return_changes=True).run(conn)
try:
got_item = do['changes'][0]['new_val']['id']
last_used = do['changes'][0]['new_val']['last_used']
except:
# print('error', do)
raise self.retry()
if got_item:
# Do stuff that required unique row here....
print(got_item,'\n',last_used)
time.sleep(random.randrange(1,5))
r.db('').table('').get(got_item).update({"status": 1}).run(conn)
#start workers
for i in range(50):
ss.delay()
Надеюсь, с этим работники гарантированно будут работать с уникальным элементом внутри блока if if_item.