| 5146 | } |
| 5147 | |
| 5148 | bool client::asyncCommand(std::function<void(const redisDbPersistentDataSnapshot *, const std::vector<robj_sharedptr> &)> &&mainFn, |
| 5149 | std::function<void(const redisDbPersistentDataSnapshot *)> &&postFn) |
| 5150 | { |
| 5151 | serverAssert(FCorrectThread(this)); |
| 5152 | if (serverTL->in_eval) |
| 5153 | return false; // we cannot block clients in EVAL |
| 5154 | const redisDbPersistentDataSnapshot *snapshot = nullptr; |
| 5155 | if (!(this->flags & (CLIENT_MULTI | CLIENT_BLOCKED))) |
| 5156 | snapshot = this->db->createSnapshot(this->mvccCheckpoint, false /* fOptional */); |
| 5157 | if (snapshot == nullptr) { |
| 5158 | return false; |
| 5159 | } |
| 5160 | aeEventLoop *el = serverTL->el; |
| 5161 | blockClient(this, BLOCKED_ASYNC); |
| 5162 | g_pserver->asyncworkqueue->AddWorkFunction([el, this, mainFn, postFn, snapshot] { |
| 5163 | std::vector<robj_sharedptr> args = clientArgs(this); |
| 5164 | aePostFunction(el, [this, mainFn, postFn, snapshot, args] { |
| 5165 | aeReleaseLock(); |
| 5166 | std::unique_lock<decltype(this->lock)> lock(this->lock); |
| 5167 | AeLocker locker; |
| 5168 | locker.arm(this); |
| 5169 | unblockClient(this); |
| 5170 | mainFn(snapshot, args); |
| 5171 | locker.disarm(); |
| 5172 | lock.unlock(); |
| 5173 | if (postFn) |
| 5174 | postFn(snapshot); |
| 5175 | this->db->endSnapshotAsync(snapshot); |
| 5176 | aeAcquireLock(); |
| 5177 | }); |
| 5178 | }); |
| 5179 | return true; |
| 5180 | } |
| 5181 | |
| 5182 | /* ====================== Error lookup and execution ===================== */ |
| 5183 |
no test coverage detected