fix: improve consistency around brpop flow

1. Added a test that was breaking earlier.
2. Made sure that multiple waked brpop transaction would not
   snatch items from one another.
3. Fixed watched-queues clean-up logic inside blocking_controller that caused deadlocks.

Signed-off-by: Roman Gershman <roman@dragonflydb.io>
This commit is contained in:
Roman Gershman 2023-03-17 09:07:10 +02:00 committed by Roman Gershman
parent c96f637f73
commit f4081f3979
7 changed files with 214 additions and 155 deletions

View file

@ -28,22 +28,18 @@ class BlockingController {
return awakened_transactions_;
}
// Iterates over awakened key candidates in each db and moves verified ones into
// global verified_awakened_ array.
// Returns true if there are active awakened keys, false otherwise.
// It has 2 responsibilities.
// 1: to go over potential wakened keys, verify them and activate watch queues.
// 2: if t is awaked and finished running - to remove it from the head
// of the queue and notify the next one.
// If t is null then second part is omitted.
void RunStep(Transaction* t);
void FinalizeWatched(KeyLockArgs lock_args, Transaction* tx);
// A mirror reflection but with ArgSlice. Yeah, I know....
void FinalizeWatched(ArgSlice args, Transaction* tx);
// go over potential wakened keys, verify them and activate watch queues.
void NotifyPending();
// Blocking API
// TODO: consider moving all watched functions to
// EngineShard with separate per db map.
//! AddWatched adds a transaction to the blocking queue.
void AddWatched(ArgSlice watch_keys, Transaction* me);
void RemoveWatched(ArgSlice watch_keys, Transaction* me);
// Called from operations that create keys like lpush, rename etc.
void AwakeWatched(DbIndex db_index, std::string_view db_key);
@ -52,10 +48,6 @@ class BlockingController {
size_t NumWatched(DbIndex db_indx) const;
std::vector<std::string> GetWatchedKeys(DbIndex db_indx) const;
void RemoveAwaked(Transaction* trans) {
awakened_transactions_.erase(trans);
}
private:
struct WatchQueue;
struct DbWatchTable;