1 /************************************************************************** 2 Copyright (c) 2017 sewenew 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 *************************************************************************/ 16 17 #ifndef SEWENEW_REDISPLUSPLUS_QUEUED_REDIS_H 18 #define SEWENEW_REDISPLUSPLUS_QUEUED_REDIS_H 19 20 #include <cassert> 21 #include <chrono> 22 #include <initializer_list> 23 #include <vector> 24 #include "connection.h" 25 #include "utils.h" 26 #include "reply.h" 27 #include "command.h" 28 #include "redis.h" 29 30 namespace sw { 31 32 namespace redis { 33 34 class QueuedReplies; 35 36 // If any command throws, QueuedRedis resets the connection, and becomes invalid. 37 // In this case, the only thing we can do is to destory the QueuedRedis object. 38 template <typename Impl> 39 class QueuedRedis { 40 public: 41 QueuedRedis(QueuedRedis &&) = default; 42 QueuedRedis& operator=(QueuedRedis &&) = default; 43 44 // When it destructs, the underlying *Connection* will be closed, 45 // and any command that has NOT been executed will be ignored. 46 ~QueuedRedis() = default; 47 48 Redis redis(); 49 50 template <typename Cmd, typename ...Args> 51 auto command(Cmd cmd, Args &&...args) 52 -> typename std::enable_if<!std::is_convertible<Cmd, StringView>::value, 53 QueuedRedis&>::type; 54 55 template <typename ...Args> 56 QueuedRedis& command(const StringView &cmd_name, Args &&...args); 57 58 template <typename Input> 59 auto command(Input first, Input last) 60 -> typename std::enable_if<IsIter<Input>::value, QueuedRedis&>::type; 61 62 QueuedReplies exec(); 63 64 void discard(); 65 66 // CONNECTION commands. 67 auth(const StringView & password)68 QueuedRedis& auth(const StringView &password) { 69 return command(cmd::auth, password); 70 } 71 echo(const StringView & msg)72 QueuedRedis& echo(const StringView &msg) { 73 return command(cmd::echo, msg); 74 } 75 ping()76 QueuedRedis& ping() { 77 return command<void (*)(Connection &)>(cmd::ping); 78 } 79 ping(const StringView & msg)80 QueuedRedis& ping(const StringView &msg) { 81 return command<void (*)(Connection &, const StringView &)>(cmd::ping, msg); 82 } 83 84 // We DO NOT support the QUIT command. See *Redis::quit* doc for details. 85 // 86 // QueuedRedis& quit(); 87 select(long long idx)88 QueuedRedis& select(long long idx) { 89 return command(cmd::select, idx); 90 } 91 swapdb(long long idx1,long long idx2)92 QueuedRedis& swapdb(long long idx1, long long idx2) { 93 return command(cmd::swapdb, idx1, idx2); 94 } 95 96 // SERVER commands. 97 bgrewriteaof()98 QueuedRedis& bgrewriteaof() { 99 return command(cmd::bgrewriteaof); 100 } 101 bgsave()102 QueuedRedis& bgsave() { 103 return command(cmd::bgsave); 104 } 105 dbsize()106 QueuedRedis& dbsize() { 107 return command(cmd::dbsize); 108 } 109 110 QueuedRedis& flushall(bool async = false) { 111 return command(cmd::flushall, async); 112 } 113 114 QueuedRedis& flushdb(bool async = false) { 115 return command(cmd::flushdb, async); 116 } 117 info()118 QueuedRedis& info() { 119 return command<void (*)(Connection &)>(cmd::info); 120 } 121 info(const StringView & section)122 QueuedRedis& info(const StringView §ion) { 123 return command<void (*)(Connection &, const StringView &)>(cmd::info, section); 124 } 125 lastsave()126 QueuedRedis& lastsave() { 127 return command(cmd::lastsave); 128 } 129 save()130 QueuedRedis& save() { 131 return command(cmd::save); 132 } 133 134 // KEY commands. 135 del(const StringView & key)136 QueuedRedis& del(const StringView &key) { 137 return command(cmd::del, key); 138 } 139 140 template <typename Input> del(Input first,Input last)141 QueuedRedis& del(Input first, Input last) { 142 return command(cmd::del_range<Input>, first, last); 143 } 144 145 template <typename T> del(std::initializer_list<T> il)146 QueuedRedis& del(std::initializer_list<T> il) { 147 return del(il.begin(), il.end()); 148 } 149 dump(const StringView & key)150 QueuedRedis& dump(const StringView &key) { 151 return command(cmd::dump, key); 152 } 153 exists(const StringView & key)154 QueuedRedis& exists(const StringView &key) { 155 return command(cmd::exists, key); 156 } 157 158 template <typename Input> exists(Input first,Input last)159 QueuedRedis& exists(Input first, Input last) { 160 return command(cmd::exists_range<Input>, first, last); 161 } 162 163 template <typename T> exists(std::initializer_list<T> il)164 QueuedRedis& exists(std::initializer_list<T> il) { 165 return exists(il.begin(), il.end()); 166 } 167 expire(const StringView & key,long long timeout)168 QueuedRedis& expire(const StringView &key, long long timeout) { 169 return command(cmd::expire, key, timeout); 170 } 171 expire(const StringView & key,const std::chrono::seconds & timeout)172 QueuedRedis& expire(const StringView &key, 173 const std::chrono::seconds &timeout) { 174 return expire(key, timeout.count()); 175 } 176 expireat(const StringView & key,long long timestamp)177 QueuedRedis& expireat(const StringView &key, long long timestamp) { 178 return command(cmd::expireat, key, timestamp); 179 } 180 expireat(const StringView & key,const std::chrono::time_point<std::chrono::system_clock,std::chrono::seconds> & tp)181 QueuedRedis& expireat(const StringView &key, 182 const std::chrono::time_point<std::chrono::system_clock, 183 std::chrono::seconds> &tp) { 184 return expireat(key, tp.time_since_epoch().count()); 185 } 186 keys(const StringView & pattern)187 QueuedRedis& keys(const StringView &pattern) { 188 return command(cmd::keys, pattern); 189 } 190 move(const StringView & key,long long db)191 QueuedRedis& move(const StringView &key, long long db) { 192 return command(cmd::move, key, db); 193 } 194 persist(const StringView & key)195 QueuedRedis& persist(const StringView &key) { 196 return command(cmd::persist, key); 197 } 198 pexpire(const StringView & key,long long timeout)199 QueuedRedis& pexpire(const StringView &key, long long timeout) { 200 return command(cmd::pexpire, key, timeout); 201 } 202 pexpire(const StringView & key,const std::chrono::milliseconds & timeout)203 QueuedRedis& pexpire(const StringView &key, 204 const std::chrono::milliseconds &timeout) { 205 return pexpire(key, timeout.count()); 206 } 207 pexpireat(const StringView & key,long long timestamp)208 QueuedRedis& pexpireat(const StringView &key, long long timestamp) { 209 return command(cmd::pexpireat, key, timestamp); 210 } 211 pexpireat(const StringView & key,const std::chrono::time_point<std::chrono::system_clock,std::chrono::milliseconds> & tp)212 QueuedRedis& pexpireat(const StringView &key, 213 const std::chrono::time_point<std::chrono::system_clock, 214 std::chrono::milliseconds> &tp) { 215 return pexpireat(key, tp.time_since_epoch().count()); 216 } 217 pttl(const StringView & key)218 QueuedRedis& pttl(const StringView &key) { 219 return command(cmd::pttl, key); 220 } 221 randomkey()222 QueuedRedis& randomkey() { 223 return command(cmd::randomkey); 224 } 225 rename(const StringView & key,const StringView & newkey)226 QueuedRedis& rename(const StringView &key, const StringView &newkey) { 227 return command(cmd::rename, key, newkey); 228 } 229 renamenx(const StringView & key,const StringView & newkey)230 QueuedRedis& renamenx(const StringView &key, const StringView &newkey) { 231 return command(cmd::renamenx, key, newkey); 232 } 233 234 QueuedRedis& restore(const StringView &key, 235 const StringView &val, 236 long long ttl, 237 bool replace = false) { 238 return command(cmd::restore, key, val, ttl, replace); 239 } 240 241 QueuedRedis& restore(const StringView &key, 242 const StringView &val, 243 const std::chrono::milliseconds &ttl = std::chrono::milliseconds{0}, 244 bool replace = false) { 245 return restore(key, val, ttl.count(), replace); 246 } 247 248 // TODO: sort 249 scan(long long cursor,const StringView & pattern,long long count)250 QueuedRedis& scan(long long cursor, 251 const StringView &pattern, 252 long long count) { 253 return command(cmd::scan, cursor, pattern, count); 254 } 255 scan(long long cursor)256 QueuedRedis& scan(long long cursor) { 257 return scan(cursor, "*", 10); 258 } 259 scan(long long cursor,const StringView & pattern)260 QueuedRedis& scan(long long cursor, 261 const StringView &pattern) { 262 return scan(cursor, pattern, 10); 263 } 264 scan(long long cursor,long long count)265 QueuedRedis& scan(long long cursor, 266 long long count) { 267 return scan(cursor, "*", count); 268 } 269 touch(const StringView & key)270 QueuedRedis& touch(const StringView &key) { 271 return command(cmd::touch, key); 272 } 273 274 template <typename Input> touch(Input first,Input last)275 QueuedRedis& touch(Input first, Input last) { 276 return command(cmd::touch_range<Input>, first, last); 277 } 278 279 template <typename T> touch(std::initializer_list<T> il)280 QueuedRedis& touch(std::initializer_list<T> il) { 281 return touch(il.begin(), il.end()); 282 } 283 ttl(const StringView & key)284 QueuedRedis& ttl(const StringView &key) { 285 return command(cmd::ttl, key); 286 } 287 type(const StringView & key)288 QueuedRedis& type(const StringView &key) { 289 return command(cmd::type, key); 290 } 291 unlink(const StringView & key)292 QueuedRedis& unlink(const StringView &key) { 293 return command(cmd::unlink, key); 294 } 295 296 template <typename Input> unlink(Input first,Input last)297 QueuedRedis& unlink(Input first, Input last) { 298 return command(cmd::unlink_range<Input>, first, last); 299 } 300 301 template <typename T> unlink(std::initializer_list<T> il)302 QueuedRedis& unlink(std::initializer_list<T> il) { 303 return unlink(il.begin(), il.end()); 304 } 305 wait(long long numslaves,long long timeout)306 QueuedRedis& wait(long long numslaves, long long timeout) { 307 return command(cmd::wait, numslaves, timeout); 308 } 309 wait(long long numslaves,const std::chrono::milliseconds & timeout)310 QueuedRedis& wait(long long numslaves, const std::chrono::milliseconds &timeout) { 311 return wait(numslaves, timeout.count()); 312 } 313 314 // STRING commands. 315 append(const StringView & key,const StringView & str)316 QueuedRedis& append(const StringView &key, const StringView &str) { 317 return command(cmd::append, key, str); 318 } 319 320 QueuedRedis& bitcount(const StringView &key, 321 long long start = 0, 322 long long end = -1) { 323 return command(cmd::bitcount, key, start, end); 324 } 325 bitop(BitOp op,const StringView & destination,const StringView & key)326 QueuedRedis& bitop(BitOp op, 327 const StringView &destination, 328 const StringView &key) { 329 return command(cmd::bitop, op, destination, key); 330 } 331 332 template <typename Input> bitop(BitOp op,const StringView & destination,Input first,Input last)333 QueuedRedis& bitop(BitOp op, 334 const StringView &destination, 335 Input first, 336 Input last) { 337 return command(cmd::bitop_range<Input>, op, destination, first, last); 338 } 339 340 template <typename T> bitop(BitOp op,const StringView & destination,std::initializer_list<T> il)341 QueuedRedis& bitop(BitOp op, 342 const StringView &destination, 343 std::initializer_list<T> il) { 344 return bitop(op, destination, il.begin(), il.end()); 345 } 346 347 QueuedRedis& bitpos(const StringView &key, 348 long long bit, 349 long long start = 0, 350 long long end = -1) { 351 return command(cmd::bitpos, key, bit, start, end); 352 } 353 decr(const StringView & key)354 QueuedRedis& decr(const StringView &key) { 355 return command(cmd::decr, key); 356 } 357 decrby(const StringView & key,long long decrement)358 QueuedRedis& decrby(const StringView &key, long long decrement) { 359 return command(cmd::decrby, key, decrement); 360 } 361 get(const StringView & key)362 QueuedRedis& get(const StringView &key) { 363 return command(cmd::get, key); 364 } 365 getbit(const StringView & key,long long offset)366 QueuedRedis& getbit(const StringView &key, long long offset) { 367 return command(cmd::getbit, key, offset); 368 } 369 getrange(const StringView & key,long long start,long long end)370 QueuedRedis& getrange(const StringView &key, long long start, long long end) { 371 return command(cmd::getrange, key, start, end); 372 } 373 getset(const StringView & key,const StringView & val)374 QueuedRedis& getset(const StringView &key, const StringView &val) { 375 return command(cmd::getset, key, val); 376 } 377 incr(const StringView & key)378 QueuedRedis& incr(const StringView &key) { 379 return command(cmd::incr, key); 380 } 381 incrby(const StringView & key,long long increment)382 QueuedRedis& incrby(const StringView &key, long long increment) { 383 return command(cmd::incrby, key, increment); 384 } 385 incrbyfloat(const StringView & key,double increment)386 QueuedRedis& incrbyfloat(const StringView &key, double increment) { 387 return command(cmd::incrbyfloat, key, increment); 388 } 389 390 template <typename Input> mget(Input first,Input last)391 QueuedRedis& mget(Input first, Input last) { 392 return command(cmd::mget<Input>, first, last); 393 } 394 395 template <typename T> mget(std::initializer_list<T> il)396 QueuedRedis& mget(std::initializer_list<T> il) { 397 return mget(il.begin(), il.end()); 398 } 399 400 template <typename Input> mset(Input first,Input last)401 QueuedRedis& mset(Input first, Input last) { 402 return command(cmd::mset<Input>, first, last); 403 } 404 405 template <typename T> mset(std::initializer_list<T> il)406 QueuedRedis& mset(std::initializer_list<T> il) { 407 return mset(il.begin(), il.end()); 408 } 409 410 template <typename Input> msetnx(Input first,Input last)411 QueuedRedis& msetnx(Input first, Input last) { 412 return command(cmd::msetnx<Input>, first, last); 413 } 414 415 template <typename T> msetnx(std::initializer_list<T> il)416 QueuedRedis& msetnx(std::initializer_list<T> il) { 417 return msetnx(il.begin(), il.end()); 418 } 419 psetex(const StringView & key,long long ttl,const StringView & val)420 QueuedRedis& psetex(const StringView &key, 421 long long ttl, 422 const StringView &val) { 423 return command(cmd::psetex, key, ttl, val); 424 } 425 psetex(const StringView & key,const std::chrono::milliseconds & ttl,const StringView & val)426 QueuedRedis& psetex(const StringView &key, 427 const std::chrono::milliseconds &ttl, 428 const StringView &val) { 429 return psetex(key, ttl.count(), val); 430 } 431 432 QueuedRedis& set(const StringView &key, 433 const StringView &val, 434 const std::chrono::milliseconds &ttl = std::chrono::milliseconds(0), 435 UpdateType type = UpdateType::ALWAYS) { 436 _set_cmd_indexes.push_back(_cmd_num); 437 438 return command(cmd::set, key, val, ttl.count(), type); 439 } 440 setex(const StringView & key,long long ttl,const StringView & val)441 QueuedRedis& setex(const StringView &key, 442 long long ttl, 443 const StringView &val) { 444 return command(cmd::setex, key, ttl, val); 445 } 446 setex(const StringView & key,const std::chrono::seconds & ttl,const StringView & val)447 QueuedRedis& setex(const StringView &key, 448 const std::chrono::seconds &ttl, 449 const StringView &val) { 450 return setex(key, ttl.count(), val); 451 } 452 setnx(const StringView & key,const StringView & val)453 QueuedRedis& setnx(const StringView &key, const StringView &val) { 454 return command(cmd::setnx, key, val); 455 } 456 setrange(const StringView & key,long long offset,const StringView & val)457 QueuedRedis& setrange(const StringView &key, 458 long long offset, 459 const StringView &val) { 460 return command(cmd::setrange, key, offset, val); 461 } 462 strlen(const StringView & key)463 QueuedRedis& strlen(const StringView &key) { 464 return command(cmd::strlen, key); 465 } 466 467 // LIST commands. 468 blpop(const StringView & key,long long timeout)469 QueuedRedis& blpop(const StringView &key, long long timeout) { 470 return command(cmd::blpop, key, timeout); 471 } 472 473 QueuedRedis& blpop(const StringView &key, 474 const std::chrono::seconds &timeout = std::chrono::seconds{0}) { 475 return blpop(key, timeout.count()); 476 } 477 478 template <typename Input> blpop(Input first,Input last,long long timeout)479 QueuedRedis& blpop(Input first, Input last, long long timeout) { 480 return command(cmd::blpop_range<Input>, first, last, timeout); 481 } 482 483 template <typename T> blpop(std::initializer_list<T> il,long long timeout)484 QueuedRedis& blpop(std::initializer_list<T> il, long long timeout) { 485 return blpop(il.begin(), il.end(), timeout); 486 } 487 488 template <typename Input> 489 QueuedRedis& blpop(Input first, 490 Input last, 491 const std::chrono::seconds &timeout = std::chrono::seconds{0}) { 492 return blpop(first, last, timeout.count()); 493 } 494 495 template <typename T> 496 QueuedRedis& blpop(std::initializer_list<T> il, 497 const std::chrono::seconds &timeout = std::chrono::seconds{0}) { 498 return blpop(il.begin(), il.end(), timeout); 499 } 500 brpop(const StringView & key,long long timeout)501 QueuedRedis& brpop(const StringView &key, long long timeout) { 502 return command(cmd::brpop, key, timeout); 503 } 504 505 QueuedRedis& brpop(const StringView &key, 506 const std::chrono::seconds &timeout = std::chrono::seconds{0}) { 507 return brpop(key, timeout.count()); 508 } 509 510 template <typename Input> brpop(Input first,Input last,long long timeout)511 QueuedRedis& brpop(Input first, Input last, long long timeout) { 512 return command(cmd::brpop_range<Input>, first, last, timeout); 513 } 514 515 template <typename T> brpop(std::initializer_list<T> il,long long timeout)516 QueuedRedis& brpop(std::initializer_list<T> il, long long timeout) { 517 return brpop(il.begin(), il.end(), timeout); 518 } 519 520 template <typename Input> 521 QueuedRedis& brpop(Input first, 522 Input last, 523 const std::chrono::seconds &timeout = std::chrono::seconds{0}) { 524 return brpop(first, last, timeout.count()); 525 } 526 527 template <typename T> 528 QueuedRedis& brpop(std::initializer_list<T> il, 529 const std::chrono::seconds &timeout = std::chrono::seconds{0}) { 530 return brpop(il.begin(), il.end(), timeout); 531 } 532 brpoplpush(const StringView & source,const StringView & destination,long long timeout)533 QueuedRedis& brpoplpush(const StringView &source, 534 const StringView &destination, 535 long long timeout) { 536 return command(cmd::brpoplpush, source, destination, timeout); 537 } 538 539 QueuedRedis& brpoplpush(const StringView &source, 540 const StringView &destination, 541 const std::chrono::seconds &timeout = std::chrono::seconds{0}) { 542 return brpoplpush(source, destination, timeout.count()); 543 } 544 lindex(const StringView & key,long long index)545 QueuedRedis& lindex(const StringView &key, long long index) { 546 return command(cmd::lindex, key, index); 547 } 548 linsert(const StringView & key,InsertPosition position,const StringView & pivot,const StringView & val)549 QueuedRedis& linsert(const StringView &key, 550 InsertPosition position, 551 const StringView &pivot, 552 const StringView &val) { 553 return command(cmd::linsert, key, position, pivot, val); 554 } 555 llen(const StringView & key)556 QueuedRedis& llen(const StringView &key) { 557 return command(cmd::llen, key); 558 } 559 lpop(const StringView & key)560 QueuedRedis& lpop(const StringView &key) { 561 return command(cmd::lpop, key); 562 } 563 lpush(const StringView & key,const StringView & val)564 QueuedRedis& lpush(const StringView &key, const StringView &val) { 565 return command(cmd::lpush, key, val); 566 } 567 568 template <typename Input> lpush(const StringView & key,Input first,Input last)569 QueuedRedis& lpush(const StringView &key, Input first, Input last) { 570 return command(cmd::lpush_range<Input>, key, first, last); 571 } 572 573 template <typename T> lpush(const StringView & key,std::initializer_list<T> il)574 QueuedRedis& lpush(const StringView &key, std::initializer_list<T> il) { 575 return lpush(key, il.begin(), il.end()); 576 } 577 lpushx(const StringView & key,const StringView & val)578 QueuedRedis& lpushx(const StringView &key, const StringView &val) { 579 return command(cmd::lpushx, key, val); 580 } 581 lrange(const StringView & key,long long start,long long stop)582 QueuedRedis& lrange(const StringView &key, 583 long long start, 584 long long stop) { 585 return command(cmd::lrange, key, start, stop); 586 } 587 lrem(const StringView & key,long long count,const StringView & val)588 QueuedRedis& lrem(const StringView &key, long long count, const StringView &val) { 589 return command(cmd::lrem, key, count, val); 590 } 591 lset(const StringView & key,long long index,const StringView & val)592 QueuedRedis& lset(const StringView &key, long long index, const StringView &val) { 593 return command(cmd::lset, key, index, val); 594 } 595 ltrim(const StringView & key,long long start,long long stop)596 QueuedRedis& ltrim(const StringView &key, long long start, long long stop) { 597 return command(cmd::ltrim, key, start, stop); 598 } 599 rpop(const StringView & key)600 QueuedRedis& rpop(const StringView &key) { 601 return command(cmd::rpop, key); 602 } 603 rpoplpush(const StringView & source,const StringView & destination)604 QueuedRedis& rpoplpush(const StringView &source, const StringView &destination) { 605 return command(cmd::rpoplpush, source, destination); 606 } 607 rpush(const StringView & key,const StringView & val)608 QueuedRedis& rpush(const StringView &key, const StringView &val) { 609 return command(cmd::rpush, key, val); 610 } 611 612 template <typename Input> rpush(const StringView & key,Input first,Input last)613 QueuedRedis& rpush(const StringView &key, Input first, Input last) { 614 return command(cmd::rpush_range<Input>, key, first, last); 615 } 616 617 template <typename T> rpush(const StringView & key,std::initializer_list<T> il)618 QueuedRedis& rpush(const StringView &key, std::initializer_list<T> il) { 619 return rpush(key, il.begin(), il.end()); 620 } 621 rpushx(const StringView & key,const StringView & val)622 QueuedRedis& rpushx(const StringView &key, const StringView &val) { 623 return command(cmd::rpushx, key, val); 624 } 625 626 // HASH commands. 627 hdel(const StringView & key,const StringView & field)628 QueuedRedis& hdel(const StringView &key, const StringView &field) { 629 return command(cmd::hdel, key, field); 630 } 631 632 template <typename Input> hdel(const StringView & key,Input first,Input last)633 QueuedRedis& hdel(const StringView &key, Input first, Input last) { 634 return command(cmd::hdel_range<Input>, key, first, last); 635 } 636 637 template <typename T> hdel(const StringView & key,std::initializer_list<T> il)638 QueuedRedis& hdel(const StringView &key, std::initializer_list<T> il) { 639 return hdel(key, il.begin(), il.end()); 640 } 641 hexists(const StringView & key,const StringView & field)642 QueuedRedis& hexists(const StringView &key, const StringView &field) { 643 return command(cmd::hexists, key, field); 644 } 645 hget(const StringView & key,const StringView & field)646 QueuedRedis& hget(const StringView &key, const StringView &field) { 647 return command(cmd::hget, key, field); 648 } 649 hgetall(const StringView & key)650 QueuedRedis& hgetall(const StringView &key) { 651 return command(cmd::hgetall, key); 652 } 653 hincrby(const StringView & key,const StringView & field,long long increment)654 QueuedRedis& hincrby(const StringView &key, 655 const StringView &field, 656 long long increment) { 657 return command(cmd::hincrby, key, field, increment); 658 } 659 hincrbyfloat(const StringView & key,const StringView & field,double increment)660 QueuedRedis& hincrbyfloat(const StringView &key, 661 const StringView &field, 662 double increment) { 663 return command(cmd::hincrbyfloat, key, field, increment); 664 } 665 hkeys(const StringView & key)666 QueuedRedis& hkeys(const StringView &key) { 667 return command(cmd::hkeys, key); 668 } 669 hlen(const StringView & key)670 QueuedRedis& hlen(const StringView &key) { 671 return command(cmd::hlen, key); 672 } 673 674 template <typename Input> hmget(const StringView & key,Input first,Input last)675 QueuedRedis& hmget(const StringView &key, Input first, Input last) { 676 return command(cmd::hmget<Input>, key, first, last); 677 } 678 679 template <typename T> hmget(const StringView & key,std::initializer_list<T> il)680 QueuedRedis& hmget(const StringView &key, std::initializer_list<T> il) { 681 return hmget(key, il.begin(), il.end()); 682 } 683 684 template <typename Input> hmset(const StringView & key,Input first,Input last)685 QueuedRedis& hmset(const StringView &key, Input first, Input last) { 686 return command(cmd::hmset<Input>, key, first, last); 687 } 688 689 template <typename T> hmset(const StringView & key,std::initializer_list<T> il)690 QueuedRedis& hmset(const StringView &key, std::initializer_list<T> il) { 691 return hmset(key, il.begin(), il.end()); 692 } 693 hscan(const StringView & key,long long cursor,const StringView & pattern,long long count)694 QueuedRedis& hscan(const StringView &key, 695 long long cursor, 696 const StringView &pattern, 697 long long count) { 698 return command(cmd::hscan, key, cursor, pattern, count); 699 } 700 hscan(const StringView & key,long long cursor,const StringView & pattern)701 QueuedRedis& hscan(const StringView &key, 702 long long cursor, 703 const StringView &pattern) { 704 return hscan(key, cursor, pattern, 10); 705 } 706 hscan(const StringView & key,long long cursor,long long count)707 QueuedRedis& hscan(const StringView &key, 708 long long cursor, 709 long long count) { 710 return hscan(key, cursor, "*", count); 711 } 712 hscan(const StringView & key,long long cursor)713 QueuedRedis& hscan(const StringView &key, 714 long long cursor) { 715 return hscan(key, cursor, "*", 10); 716 } 717 hset(const StringView & key,const StringView & field,const StringView & val)718 QueuedRedis& hset(const StringView &key, const StringView &field, const StringView &val) { 719 return command(cmd::hset, key, field, val); 720 } 721 hset(const StringView & key,const std::pair<StringView,StringView> & item)722 QueuedRedis& hset(const StringView &key, const std::pair<StringView, StringView> &item) { 723 return hset(key, item.first, item.second); 724 } 725 hsetnx(const StringView & key,const StringView & field,const StringView & val)726 QueuedRedis& hsetnx(const StringView &key, const StringView &field, const StringView &val) { 727 return command(cmd::hsetnx, key, field, val); 728 } 729 hsetnx(const StringView & key,const std::pair<StringView,StringView> & item)730 QueuedRedis& hsetnx(const StringView &key, const std::pair<StringView, StringView> &item) { 731 return hsetnx(key, item.first, item.second); 732 } 733 hstrlen(const StringView & key,const StringView & field)734 QueuedRedis& hstrlen(const StringView &key, const StringView &field) { 735 return command(cmd::hstrlen, key, field); 736 } 737 hvals(const StringView & key)738 QueuedRedis& hvals(const StringView &key) { 739 return command(cmd::hvals, key); 740 } 741 742 // SET commands. 743 sadd(const StringView & key,const StringView & member)744 QueuedRedis& sadd(const StringView &key, const StringView &member) { 745 return command(cmd::sadd, key, member); 746 } 747 748 template <typename Input> sadd(const StringView & key,Input first,Input last)749 QueuedRedis& sadd(const StringView &key, Input first, Input last) { 750 return command(cmd::sadd_range<Input>, key, first, last); 751 } 752 753 template <typename T> sadd(const StringView & key,std::initializer_list<T> il)754 QueuedRedis& sadd(const StringView &key, std::initializer_list<T> il) { 755 return sadd(key, il.begin(), il.end()); 756 } 757 scard(const StringView & key)758 QueuedRedis& scard(const StringView &key) { 759 return command(cmd::scard, key); 760 } 761 762 template <typename Input> sdiff(Input first,Input last)763 QueuedRedis& sdiff(Input first, Input last) { 764 return command(cmd::sdiff<Input>, first, last); 765 } 766 767 template <typename T> sdiff(std::initializer_list<T> il)768 QueuedRedis& sdiff(std::initializer_list<T> il) { 769 return sdiff(il.begin(), il.end()); 770 } 771 sdiffstore(const StringView & destination,const StringView & key)772 QueuedRedis& sdiffstore(const StringView &destination, const StringView &key) { 773 return command(cmd::sdiffstore, destination, key); 774 } 775 776 template <typename Input> sdiffstore(const StringView & destination,Input first,Input last)777 QueuedRedis& sdiffstore(const StringView &destination, 778 Input first, 779 Input last) { 780 return command(cmd::sdiffstore_range<Input>, destination, first, last); 781 } 782 783 template <typename T> sdiffstore(const StringView & destination,std::initializer_list<T> il)784 QueuedRedis& sdiffstore(const StringView &destination, std::initializer_list<T> il) { 785 return sdiffstore(destination, il.begin(), il.end()); 786 } 787 788 template <typename Input> sinter(Input first,Input last)789 QueuedRedis& sinter(Input first, Input last) { 790 return command(cmd::sinter<Input>, first, last); 791 } 792 793 template <typename T> sinter(std::initializer_list<T> il)794 QueuedRedis& sinter(std::initializer_list<T> il) { 795 return sinter(il.begin(), il.end()); 796 } 797 sinterstore(const StringView & destination,const StringView & key)798 QueuedRedis& sinterstore(const StringView &destination, const StringView &key) { 799 return command(cmd::sinterstore, destination, key); 800 } 801 802 template <typename Input> sinterstore(const StringView & destination,Input first,Input last)803 QueuedRedis& sinterstore(const StringView &destination, 804 Input first, 805 Input last) { 806 return command(cmd::sinterstore_range<Input>, destination, first, last); 807 } 808 809 template <typename T> sinterstore(const StringView & destination,std::initializer_list<T> il)810 QueuedRedis& sinterstore(const StringView &destination, std::initializer_list<T> il) { 811 return sinterstore(destination, il.begin(), il.end()); 812 } 813 sismember(const StringView & key,const StringView & member)814 QueuedRedis& sismember(const StringView &key, const StringView &member) { 815 return command(cmd::sismember, key, member); 816 } 817 smembers(const StringView & key)818 QueuedRedis& smembers(const StringView &key) { 819 return command(cmd::smembers, key); 820 } 821 smove(const StringView & source,const StringView & destination,const StringView & member)822 QueuedRedis& smove(const StringView &source, 823 const StringView &destination, 824 const StringView &member) { 825 return command(cmd::smove, source, destination, member); 826 } 827 spop(const StringView & key)828 QueuedRedis& spop(const StringView &key) { 829 return command(cmd::spop, key); 830 } 831 spop(const StringView & key,long long count)832 QueuedRedis& spop(const StringView &key, long long count) { 833 return command(cmd::spop_range, key, count); 834 } 835 srandmember(const StringView & key)836 QueuedRedis& srandmember(const StringView &key) { 837 return command(cmd::srandmember, key); 838 } 839 srandmember(const StringView & key,long long count)840 QueuedRedis& srandmember(const StringView &key, long long count) { 841 return command(cmd::srandmember_range, key, count); 842 } 843 srem(const StringView & key,const StringView & member)844 QueuedRedis& srem(const StringView &key, const StringView &member) { 845 return command(cmd::srem, key, member); 846 } 847 848 template <typename Input> srem(const StringView & key,Input first,Input last)849 QueuedRedis& srem(const StringView &key, Input first, Input last) { 850 return command(cmd::srem_range<Input>, key, first, last); 851 } 852 853 template <typename T> srem(const StringView & key,std::initializer_list<T> il)854 QueuedRedis& srem(const StringView &key, std::initializer_list<T> il) { 855 return srem(key, il.begin(), il.end()); 856 } 857 sscan(const StringView & key,long long cursor,const StringView & pattern,long long count)858 QueuedRedis& sscan(const StringView &key, 859 long long cursor, 860 const StringView &pattern, 861 long long count) { 862 return command(cmd::sscan, key, cursor, pattern, count); 863 } 864 sscan(const StringView & key,long long cursor,const StringView & pattern)865 QueuedRedis& sscan(const StringView &key, 866 long long cursor, 867 const StringView &pattern) { 868 return sscan(key, cursor, pattern, 10); 869 } 870 sscan(const StringView & key,long long cursor,long long count)871 QueuedRedis& sscan(const StringView &key, 872 long long cursor, 873 long long count) { 874 return sscan(key, cursor, "*", count); 875 } 876 sscan(const StringView & key,long long cursor)877 QueuedRedis& sscan(const StringView &key, 878 long long cursor) { 879 return sscan(key, cursor, "*", 10); 880 } 881 882 template <typename Input> sunion(Input first,Input last)883 QueuedRedis& sunion(Input first, Input last) { 884 return command(cmd::sunion<Input>, first, last); 885 } 886 887 template <typename T> sunion(std::initializer_list<T> il)888 QueuedRedis& sunion(std::initializer_list<T> il) { 889 return sunion(il.begin(), il.end()); 890 } 891 sunionstore(const StringView & destination,const StringView & key)892 QueuedRedis& sunionstore(const StringView &destination, const StringView &key) { 893 return command(cmd::sunionstore, destination, key); 894 } 895 896 template <typename Input> sunionstore(const StringView & destination,Input first,Input last)897 QueuedRedis& sunionstore(const StringView &destination, Input first, Input last) { 898 return command(cmd::sunionstore_range<Input>, destination, first, last); 899 } 900 901 template <typename T> sunionstore(const StringView & destination,std::initializer_list<T> il)902 QueuedRedis& sunionstore(const StringView &destination, std::initializer_list<T> il) { 903 return sunionstore(destination, il.begin(), il.end()); 904 } 905 906 // SORTED SET commands. 907 bzpopmax(const StringView & key,long long timeout)908 QueuedRedis& bzpopmax(const StringView &key, long long timeout) { 909 return command(cmd::bzpopmax, key, timeout); 910 } 911 912 QueuedRedis& bzpopmax(const StringView &key, 913 const std::chrono::seconds &timeout = std::chrono::seconds{0}) { 914 return bzpopmax(key, timeout.count()); 915 } 916 917 template <typename Input> bzpopmax(Input first,Input last,long long timeout)918 QueuedRedis& bzpopmax(Input first, Input last, long long timeout) { 919 return command(cmd::bzpopmax_range<Input>, first, last, timeout); 920 } 921 922 template <typename Input> 923 QueuedRedis& bzpopmax(Input first, 924 Input last, 925 const std::chrono::seconds &timeout = std::chrono::seconds{0}) { 926 return bzpopmax(first, last, timeout.count()); 927 } 928 929 template <typename T> bzpopmax(std::initializer_list<T> il,long long timeout)930 QueuedRedis& bzpopmax(std::initializer_list<T> il, long long timeout) { 931 return bzpopmax(il.begin(), il.end(), timeout); 932 } 933 934 template <typename T> 935 QueuedRedis& bzpopmax(std::initializer_list<T> il, 936 const std::chrono::seconds &timeout = std::chrono::seconds{0}) { 937 return bzpopmax(il.begin(), il.end(), timeout); 938 } 939 bzpopmin(const StringView & key,long long timeout)940 QueuedRedis& bzpopmin(const StringView &key, long long timeout) { 941 return command(cmd::bzpopmin, key, timeout); 942 } 943 944 QueuedRedis& bzpopmin(const StringView &key, 945 const std::chrono::seconds &timeout = std::chrono::seconds{0}) { 946 return bzpopmin(key, timeout.count()); 947 } 948 949 template <typename Input> bzpopmin(Input first,Input last,long long timeout)950 QueuedRedis& bzpopmin(Input first, Input last, long long timeout) { 951 return command(cmd::bzpopmin_range<Input>, first, last, timeout); 952 } 953 954 template <typename Input> 955 QueuedRedis& bzpopmin(Input first, 956 Input last, 957 const std::chrono::seconds &timeout = std::chrono::seconds{0}) { 958 return bzpopmin(first, last, timeout.count()); 959 } 960 961 template <typename T> bzpopmin(std::initializer_list<T> il,long long timeout)962 QueuedRedis& bzpopmin(std::initializer_list<T> il, long long timeout) { 963 return bzpopmin(il.begin(), il.end(), timeout); 964 } 965 966 template <typename T> 967 QueuedRedis& bzpopmin(std::initializer_list<T> il, 968 const std::chrono::seconds &timeout = std::chrono::seconds{0}) { 969 return bzpopmin(il.begin(), il.end(), timeout); 970 } 971 972 // We don't support the INCR option, since you can always use ZINCRBY instead. 973 QueuedRedis& zadd(const StringView &key, 974 const StringView &member, 975 double score, 976 UpdateType type = UpdateType::ALWAYS, 977 bool changed = false) { 978 return command(cmd::zadd, key, member, score, type, changed); 979 } 980 981 template <typename Input> 982 QueuedRedis& zadd(const StringView &key, 983 Input first, 984 Input last, 985 UpdateType type = UpdateType::ALWAYS, 986 bool changed = false) { 987 return command(cmd::zadd_range<Input>, key, first, last, type, changed); 988 } 989 zcard(const StringView & key)990 QueuedRedis& zcard(const StringView &key) { 991 return command(cmd::zcard, key); 992 } 993 994 template <typename Interval> zcount(const StringView & key,const Interval & interval)995 QueuedRedis& zcount(const StringView &key, const Interval &interval) { 996 return command(cmd::zcount<Interval>, key, interval); 997 } 998 zincrby(const StringView & key,double increment,const StringView & member)999 QueuedRedis& zincrby(const StringView &key, double increment, const StringView &member) { 1000 return command(cmd::zincrby, key, increment, member); 1001 } 1002 zinterstore(const StringView & destination,const StringView & key,double weight)1003 QueuedRedis& zinterstore(const StringView &destination, 1004 const StringView &key, 1005 double weight) { 1006 return command(cmd::zinterstore, destination, key, weight); 1007 } 1008 1009 template <typename Input> 1010 QueuedRedis& zinterstore(const StringView &destination, 1011 Input first, 1012 Input last, 1013 Aggregation type = Aggregation::SUM) { 1014 return command(cmd::zinterstore_range<Input>, destination, first, last, type); 1015 } 1016 1017 template <typename T> 1018 QueuedRedis& zinterstore(const StringView &destination, 1019 std::initializer_list<T> il, 1020 Aggregation type = Aggregation::SUM) { 1021 return zinterstore(destination, il.begin(), il.end(), type); 1022 } 1023 1024 template <typename Interval> zlexcount(const StringView & key,const Interval & interval)1025 QueuedRedis& zlexcount(const StringView &key, const Interval &interval) { 1026 return command(cmd::zlexcount<Interval>, key, interval); 1027 } 1028 zpopmax(const StringView & key)1029 QueuedRedis& zpopmax(const StringView &key) { 1030 return command(cmd::zpopmax, key, 1); 1031 } 1032 zpopmax(const StringView & key,long long count)1033 QueuedRedis& zpopmax(const StringView &key, long long count) { 1034 return command(cmd::zpopmax, key, count); 1035 } 1036 zpopmin(const StringView & key)1037 QueuedRedis& zpopmin(const StringView &key) { 1038 return command(cmd::zpopmin, key, 1); 1039 } 1040 zpopmin(const StringView & key,long long count)1041 QueuedRedis& zpopmin(const StringView &key, long long count) { 1042 return command(cmd::zpopmin, key, count); 1043 } 1044 1045 // NOTE: *QueuedRedis::zrange*'s parameters are different from *Redis::zrange*. 1046 // *Redis::zrange* is overloaded by the output iterator, however, there's no such 1047 // iterator in *QueuedRedis::zrange*. So we have to use an extra parameter: *with_scores*, 1048 // to decide whether we should send *WITHSCORES* option to Redis. This also applies to 1049 // other commands with the *WITHSCORES* option, e.g. *ZRANGEBYSCORE*, *ZREVRANGE*, 1050 // *ZREVRANGEBYSCORE*. 1051 QueuedRedis& zrange(const StringView &key, 1052 long long start, 1053 long long stop, 1054 bool with_scores = false) { 1055 return command(cmd::zrange, key, start, stop, with_scores); 1056 } 1057 1058 template <typename Interval> zrangebylex(const StringView & key,const Interval & interval,const LimitOptions & opts)1059 QueuedRedis& zrangebylex(const StringView &key, 1060 const Interval &interval, 1061 const LimitOptions &opts) { 1062 return command(cmd::zrangebylex<Interval>, key, interval, opts); 1063 } 1064 1065 template <typename Interval> zrangebylex(const StringView & key,const Interval & interval)1066 QueuedRedis& zrangebylex(const StringView &key, const Interval &interval) { 1067 return zrangebylex(key, interval, {}); 1068 } 1069 1070 // See comments on *ZRANGE*. 1071 template <typename Interval> 1072 QueuedRedis& zrangebyscore(const StringView &key, 1073 const Interval &interval, 1074 const LimitOptions &opts, 1075 bool with_scores = false) { 1076 return command(cmd::zrangebyscore<Interval>, key, interval, opts, with_scores); 1077 } 1078 1079 // See comments on *ZRANGE*. 1080 template <typename Interval> 1081 QueuedRedis& zrangebyscore(const StringView &key, 1082 const Interval &interval, 1083 bool with_scores = false) { 1084 return zrangebyscore(key, interval, {}, with_scores); 1085 } 1086 zrank(const StringView & key,const StringView & member)1087 QueuedRedis& zrank(const StringView &key, const StringView &member) { 1088 return command(cmd::zrank, key, member); 1089 } 1090 zrem(const StringView & key,const StringView & member)1091 QueuedRedis& zrem(const StringView &key, const StringView &member) { 1092 return command(cmd::zrem, key, member); 1093 } 1094 1095 template <typename Input> zrem(const StringView & key,Input first,Input last)1096 QueuedRedis& zrem(const StringView &key, Input first, Input last) { 1097 return command(cmd::zrem_range<Input>, key, first, last); 1098 } 1099 1100 template <typename T> zrem(const StringView & key,std::initializer_list<T> il)1101 QueuedRedis& zrem(const StringView &key, std::initializer_list<T> il) { 1102 return zrem(key, il.begin(), il.end()); 1103 } 1104 1105 template <typename Interval> zremrangebylex(const StringView & key,const Interval & interval)1106 QueuedRedis& zremrangebylex(const StringView &key, const Interval &interval) { 1107 return command(cmd::zremrangebylex<Interval>, key, interval); 1108 } 1109 zremrangebyrank(const StringView & key,long long start,long long stop)1110 QueuedRedis& zremrangebyrank(const StringView &key, long long start, long long stop) { 1111 return command(cmd::zremrangebyrank, key, start, stop); 1112 } 1113 1114 template <typename Interval> zremrangebyscore(const StringView & key,const Interval & interval)1115 QueuedRedis& zremrangebyscore(const StringView &key, const Interval &interval) { 1116 return command(cmd::zremrangebyscore<Interval>, key, interval); 1117 } 1118 1119 // See comments on *ZRANGE*. 1120 QueuedRedis& zrevrange(const StringView &key, 1121 long long start, 1122 long long stop, 1123 bool with_scores = false) { 1124 return command(cmd::zrevrange, key, start, stop, with_scores); 1125 } 1126 1127 template <typename Interval> zrevrangebylex(const StringView & key,const Interval & interval,const LimitOptions & opts)1128 QueuedRedis& zrevrangebylex(const StringView &key, 1129 const Interval &interval, 1130 const LimitOptions &opts) { 1131 return command(cmd::zrevrangebylex<Interval>, key, interval, opts); 1132 } 1133 1134 template <typename Interval> zrevrangebylex(const StringView & key,const Interval & interval)1135 QueuedRedis& zrevrangebylex(const StringView &key, const Interval &interval) { 1136 return zrevrangebylex(key, interval, {}); 1137 } 1138 1139 // See comments on *ZRANGE*. 1140 template <typename Interval> 1141 QueuedRedis& zrevrangebyscore(const StringView &key, 1142 const Interval &interval, 1143 const LimitOptions &opts, 1144 bool with_scores = false) { 1145 return command(cmd::zrevrangebyscore<Interval>, key, interval, opts, with_scores); 1146 } 1147 1148 // See comments on *ZRANGE*. 1149 template <typename Interval> 1150 QueuedRedis& zrevrangebyscore(const StringView &key, 1151 const Interval &interval, 1152 bool with_scores = false) { 1153 return zrevrangebyscore(key, interval, {}, with_scores); 1154 } 1155 zrevrank(const StringView & key,const StringView & member)1156 QueuedRedis& zrevrank(const StringView &key, const StringView &member) { 1157 return command(cmd::zrevrank, key, member); 1158 } 1159 zscan(const StringView & key,long long cursor,const StringView & pattern,long long count)1160 QueuedRedis& zscan(const StringView &key, 1161 long long cursor, 1162 const StringView &pattern, 1163 long long count) { 1164 return command(cmd::zscan, key, cursor, pattern, count); 1165 } 1166 zscan(const StringView & key,long long cursor,const StringView & pattern)1167 QueuedRedis& zscan(const StringView &key, 1168 long long cursor, 1169 const StringView &pattern) { 1170 return zscan(key, cursor, pattern, 10); 1171 } 1172 zscan(const StringView & key,long long cursor,long long count)1173 QueuedRedis& zscan(const StringView &key, 1174 long long cursor, 1175 long long count) { 1176 return zscan(key, cursor, "*", count); 1177 } 1178 zscan(const StringView & key,long long cursor)1179 QueuedRedis& zscan(const StringView &key, 1180 long long cursor) { 1181 return zscan(key, cursor, "*", 10); 1182 } 1183 zscore(const StringView & key,const StringView & member)1184 QueuedRedis& zscore(const StringView &key, const StringView &member) { 1185 return command(cmd::zscore, key, member); 1186 } 1187 zunionstore(const StringView & destination,const StringView & key,double weight)1188 QueuedRedis& zunionstore(const StringView &destination, 1189 const StringView &key, 1190 double weight) { 1191 return command(cmd::zunionstore, destination, key, weight); 1192 } 1193 1194 template <typename Input> 1195 QueuedRedis& zunionstore(const StringView &destination, 1196 Input first, 1197 Input last, 1198 Aggregation type = Aggregation::SUM) { 1199 return command(cmd::zunionstore_range<Input>, destination, first, last, type); 1200 } 1201 1202 template <typename T> 1203 QueuedRedis& zunionstore(const StringView &destination, 1204 std::initializer_list<T> il, 1205 Aggregation type = Aggregation::SUM) { 1206 return zunionstore(destination, il.begin(), il.end(), type); 1207 } 1208 1209 // HYPERLOGLOG commands. 1210 pfadd(const StringView & key,const StringView & element)1211 QueuedRedis& pfadd(const StringView &key, const StringView &element) { 1212 return command(cmd::pfadd, key, element); 1213 } 1214 1215 template <typename Input> pfadd(const StringView & key,Input first,Input last)1216 QueuedRedis& pfadd(const StringView &key, Input first, Input last) { 1217 return command(cmd::pfadd_range<Input>, key, first, last); 1218 } 1219 1220 template <typename T> pfadd(const StringView & key,std::initializer_list<T> il)1221 QueuedRedis& pfadd(const StringView &key, std::initializer_list<T> il) { 1222 return pfadd(key, il.begin(), il.end()); 1223 } 1224 pfcount(const StringView & key)1225 QueuedRedis& pfcount(const StringView &key) { 1226 return command(cmd::pfcount, key); 1227 } 1228 1229 template <typename Input> pfcount(Input first,Input last)1230 QueuedRedis& pfcount(Input first, Input last) { 1231 return command(cmd::pfcount_range<Input>, first, last); 1232 } 1233 1234 template <typename T> pfcount(std::initializer_list<T> il)1235 QueuedRedis& pfcount(std::initializer_list<T> il) { 1236 return pfcount(il.begin(), il.end()); 1237 } 1238 pfmerge(const StringView & destination,const StringView & key)1239 QueuedRedis& pfmerge(const StringView &destination, const StringView &key) { 1240 return command(cmd::pfmerge, destination, key); 1241 } 1242 1243 template <typename Input> pfmerge(const StringView & destination,Input first,Input last)1244 QueuedRedis& pfmerge(const StringView &destination, Input first, Input last) { 1245 return command(cmd::pfmerge_range<Input>, destination, first, last); 1246 } 1247 1248 template <typename T> pfmerge(const StringView & destination,std::initializer_list<T> il)1249 QueuedRedis& pfmerge(const StringView &destination, std::initializer_list<T> il) { 1250 return pfmerge(destination, il.begin(), il.end()); 1251 } 1252 1253 // GEO commands. 1254 geoadd(const StringView & key,const std::tuple<StringView,double,double> & member)1255 QueuedRedis& geoadd(const StringView &key, 1256 const std::tuple<StringView, double, double> &member) { 1257 return command(cmd::geoadd, key, member); 1258 } 1259 1260 template <typename Input> geoadd(const StringView & key,Input first,Input last)1261 QueuedRedis& geoadd(const StringView &key, 1262 Input first, 1263 Input last) { 1264 return command(cmd::geoadd_range<Input>, key, first, last); 1265 } 1266 1267 template <typename T> geoadd(const StringView & key,std::initializer_list<T> il)1268 QueuedRedis& geoadd(const StringView &key, std::initializer_list<T> il) { 1269 return geoadd(key, il.begin(), il.end()); 1270 } 1271 1272 QueuedRedis& geodist(const StringView &key, 1273 const StringView &member1, 1274 const StringView &member2, 1275 GeoUnit unit = GeoUnit::M) { 1276 return command(cmd::geodist, key, member1, member2, unit); 1277 } 1278 1279 template <typename Input> geohash(const StringView & key,Input first,Input last)1280 QueuedRedis& geohash(const StringView &key, Input first, Input last) { 1281 return command(cmd::geohash_range<Input>, key, first, last); 1282 } 1283 1284 template <typename T> geohash(const StringView & key,std::initializer_list<T> il)1285 QueuedRedis& geohash(const StringView &key, std::initializer_list<T> il) { 1286 return geohash(key, il.begin(), il.end()); 1287 } 1288 1289 template <typename Input> geopos(const StringView & key,Input first,Input last)1290 QueuedRedis& geopos(const StringView &key, Input first, Input last) { 1291 return command(cmd::geopos_range<Input>, key, first, last); 1292 } 1293 1294 template <typename T> geopos(const StringView & key,std::initializer_list<T> il)1295 QueuedRedis& geopos(const StringView &key, std::initializer_list<T> il) { 1296 return geopos(key, il.begin(), il.end()); 1297 } 1298 1299 // TODO: 1300 // 1. since we have different overloads for georadius and georadius-store, 1301 // we might use the GEORADIUS_RO command in the future. 1302 // 2. there're too many parameters for this method, we might refactor it. georadius(const StringView & key,const std::pair<double,double> & loc,double radius,GeoUnit unit,const StringView & destination,bool store_dist,long long count)1303 QueuedRedis& georadius(const StringView &key, 1304 const std::pair<double, double> &loc, 1305 double radius, 1306 GeoUnit unit, 1307 const StringView &destination, 1308 bool store_dist, 1309 long long count) { 1310 _georadius_cmd_indexes.push_back(_cmd_num); 1311 1312 return command(cmd::georadius_store, 1313 key, 1314 loc, 1315 radius, 1316 unit, 1317 destination, 1318 store_dist, 1319 count); 1320 } 1321 1322 // NOTE: *QueuedRedis::georadius*'s parameters are different from *Redis::georadius*. 1323 // *Redis::georadius* is overloaded by the output iterator, however, there's no such 1324 // iterator in *QueuedRedis::georadius*. So we have to use extra parameters to decide 1325 // whether we should send options to Redis. This also applies to *GEORADIUSBYMEMBER*. georadius(const StringView & key,const std::pair<double,double> & loc,double radius,GeoUnit unit,long long count,bool asc,bool with_coord,bool with_dist,bool with_hash)1326 QueuedRedis& georadius(const StringView &key, 1327 const std::pair<double, double> &loc, 1328 double radius, 1329 GeoUnit unit, 1330 long long count, 1331 bool asc, 1332 bool with_coord, 1333 bool with_dist, 1334 bool with_hash) { 1335 return command(cmd::georadius, 1336 key, 1337 loc, 1338 radius, 1339 unit, 1340 count, 1341 asc, 1342 with_coord, 1343 with_dist, 1344 with_hash); 1345 } 1346 georadiusbymember(const StringView & key,const StringView & member,double radius,GeoUnit unit,const StringView & destination,bool store_dist,long long count)1347 QueuedRedis& georadiusbymember(const StringView &key, 1348 const StringView &member, 1349 double radius, 1350 GeoUnit unit, 1351 const StringView &destination, 1352 bool store_dist, 1353 long long count) { 1354 _georadius_cmd_indexes.push_back(_cmd_num); 1355 1356 return command(cmd::georadiusbymember, 1357 key, 1358 member, 1359 radius, 1360 unit, 1361 destination, 1362 store_dist, 1363 count); 1364 } 1365 1366 // See the comments on *GEORADIUS*. georadiusbymember(const StringView & key,const StringView & member,double radius,GeoUnit unit,long long count,bool asc,bool with_coord,bool with_dist,bool with_hash)1367 QueuedRedis& georadiusbymember(const StringView &key, 1368 const StringView &member, 1369 double radius, 1370 GeoUnit unit, 1371 long long count, 1372 bool asc, 1373 bool with_coord, 1374 bool with_dist, 1375 bool with_hash) { 1376 return command(cmd::georadiusbymember, 1377 key, 1378 member, 1379 radius, 1380 unit, 1381 count, 1382 asc, 1383 with_coord, 1384 with_dist, 1385 with_hash); 1386 } 1387 1388 // SCRIPTING commands. 1389 eval(const StringView & script,std::initializer_list<StringView> keys,std::initializer_list<StringView> args)1390 QueuedRedis& eval(const StringView &script, 1391 std::initializer_list<StringView> keys, 1392 std::initializer_list<StringView> args) { 1393 return command(cmd::eval, script, keys, args); 1394 } 1395 evalsha(const StringView & script,std::initializer_list<StringView> keys,std::initializer_list<StringView> args)1396 QueuedRedis& evalsha(const StringView &script, 1397 std::initializer_list<StringView> keys, 1398 std::initializer_list<StringView> args) { 1399 return command(cmd::evalsha, script, keys, args); 1400 } 1401 1402 template <typename Input> script_exists(Input first,Input last)1403 QueuedRedis& script_exists(Input first, Input last) { 1404 return command(cmd::script_exists_range<Input>, first, last); 1405 } 1406 1407 template <typename T> script_exists(std::initializer_list<T> il)1408 QueuedRedis& script_exists(std::initializer_list<T> il) { 1409 return script_exists(il.begin(), il.end()); 1410 } 1411 script_flush()1412 QueuedRedis& script_flush() { 1413 return command(cmd::script_flush); 1414 } 1415 script_kill()1416 QueuedRedis& script_kill() { 1417 return command(cmd::script_kill); 1418 } 1419 script_load(const StringView & script)1420 QueuedRedis& script_load(const StringView &script) { 1421 return command(cmd::script_load, script); 1422 } 1423 1424 // PUBSUB commands. 1425 publish(const StringView & channel,const StringView & message)1426 QueuedRedis& publish(const StringView &channel, const StringView &message) { 1427 return command(cmd::publish, channel, message); 1428 } 1429 1430 // Stream commands. 1431 xack(const StringView & key,const StringView & group,const StringView & id)1432 QueuedRedis& xack(const StringView &key, const StringView &group, const StringView &id) { 1433 return command(cmd::xack, key, group, id); 1434 } 1435 1436 template <typename Input> xack(const StringView & key,const StringView & group,Input first,Input last)1437 QueuedRedis& xack(const StringView &key, const StringView &group, Input first, Input last) { 1438 return command(cmd::xack_range<Input>, key, group, first, last); 1439 } 1440 1441 template <typename T> xack(const StringView & key,const StringView & group,std::initializer_list<T> il)1442 QueuedRedis& xack(const StringView &key, const StringView &group, std::initializer_list<T> il) { 1443 return xack(key, group, il.begin(), il.end()); 1444 } 1445 1446 template <typename Input> xadd(const StringView & key,const StringView & id,Input first,Input last)1447 QueuedRedis& xadd(const StringView &key, const StringView &id, Input first, Input last) { 1448 return command(cmd::xadd_range<Input>, key, id, first, last); 1449 } 1450 1451 template <typename T> xadd(const StringView & key,const StringView & id,std::initializer_list<T> il)1452 QueuedRedis& xadd(const StringView &key, const StringView &id, std::initializer_list<T> il) { 1453 return xadd(key, id, il.begin(), il.end()); 1454 } 1455 1456 template <typename Input> 1457 QueuedRedis& xadd(const StringView &key, 1458 const StringView &id, 1459 Input first, 1460 Input last, 1461 long long count, 1462 bool approx = true) { 1463 return command(cmd::xadd_maxlen_range<Input>, key, id, first, last, count, approx); 1464 } 1465 1466 template <typename T> 1467 QueuedRedis& xadd(const StringView &key, 1468 const StringView &id, 1469 std::initializer_list<T> il, 1470 long long count, 1471 bool approx = true) { 1472 return xadd(key, id, il.begin(), il.end(), count, approx); 1473 } 1474 xclaim(const StringView & key,const StringView & group,const StringView & consumer,const std::chrono::milliseconds & min_idle_time,const StringView & id)1475 QueuedRedis& xclaim(const StringView &key, 1476 const StringView &group, 1477 const StringView &consumer, 1478 const std::chrono::milliseconds &min_idle_time, 1479 const StringView &id) { 1480 return command(cmd::xclaim, key, group, consumer, min_idle_time.count(), id); 1481 } 1482 1483 template <typename Input> xclaim(const StringView & key,const StringView & group,const StringView & consumer,const std::chrono::milliseconds & min_idle_time,Input first,Input last)1484 QueuedRedis& xclaim(const StringView &key, 1485 const StringView &group, 1486 const StringView &consumer, 1487 const std::chrono::milliseconds &min_idle_time, 1488 Input first, 1489 Input last) { 1490 return command(cmd::xclaim_range<Input>, 1491 key, 1492 group, 1493 consumer, 1494 min_idle_time.count(), 1495 first, 1496 last); 1497 } 1498 1499 template <typename T> xclaim(const StringView & key,const StringView & group,const StringView & consumer,const std::chrono::milliseconds & min_idle_time,std::initializer_list<T> il)1500 QueuedRedis& xclaim(const StringView &key, 1501 const StringView &group, 1502 const StringView &consumer, 1503 const std::chrono::milliseconds &min_idle_time, 1504 std::initializer_list<T> il) { 1505 return xclaim(key, group, consumer, min_idle_time, il.begin(), il.end()); 1506 } 1507 xdel(const StringView & key,const StringView & id)1508 QueuedRedis& xdel(const StringView &key, const StringView &id) { 1509 return command(cmd::xdel, key, id); 1510 } 1511 1512 template <typename Input> xdel(const StringView & key,Input first,Input last)1513 QueuedRedis& xdel(const StringView &key, Input first, Input last) { 1514 return command(cmd::xdel_range<Input>, key, first, last); 1515 } 1516 1517 template <typename T> xdel(const StringView & key,std::initializer_list<T> il)1518 QueuedRedis& xdel(const StringView &key, std::initializer_list<T> il) { 1519 return xdel(key, il.begin(), il.end()); 1520 } 1521 1522 QueuedRedis& xgroup_create(const StringView &key, 1523 const StringView &group, 1524 const StringView &id, 1525 bool mkstream = false) { 1526 return command(cmd::xgroup_create, key, group, id, mkstream); 1527 } 1528 xgroup_setid(const StringView & key,const StringView & group,const StringView & id)1529 QueuedRedis& xgroup_setid(const StringView &key, 1530 const StringView &group, 1531 const StringView &id) { 1532 return command(cmd::xgroup_setid, key, group, id); 1533 } 1534 xgroup_destroy(const StringView & key,const StringView & group)1535 QueuedRedis& xgroup_destroy(const StringView &key, const StringView &group) { 1536 return command(cmd::xgroup_destroy, key, group); 1537 } 1538 xgroup_delconsumer(const StringView & key,const StringView & group,const StringView & consumer)1539 QueuedRedis& xgroup_delconsumer(const StringView &key, 1540 const StringView &group, 1541 const StringView &consumer) { 1542 return command(cmd::xgroup_delconsumer, key, group, consumer); 1543 } 1544 xlen(const StringView & key)1545 QueuedRedis& xlen(const StringView &key) { 1546 return command(cmd::xlen, key); 1547 } 1548 xpending(const StringView & key,const StringView & group)1549 QueuedRedis& xpending(const StringView &key, const StringView &group) { 1550 return command(cmd::xpending, key, group); 1551 } 1552 xpending(const StringView & key,const StringView & group,const StringView & start,const StringView & end,long long count)1553 QueuedRedis& xpending(const StringView &key, 1554 const StringView &group, 1555 const StringView &start, 1556 const StringView &end, 1557 long long count) { 1558 return command(cmd::xpending_detail, key, group, start, end, count); 1559 } 1560 xpending(const StringView & key,const StringView & group,const StringView & start,const StringView & end,long long count,const StringView & consumer)1561 QueuedRedis& xpending(const StringView &key, 1562 const StringView &group, 1563 const StringView &start, 1564 const StringView &end, 1565 long long count, 1566 const StringView &consumer) { 1567 return command(cmd::xpending_per_consumer, key, group, start, end, count, consumer); 1568 } 1569 xrange(const StringView & key,const StringView & start,const StringView & end)1570 QueuedRedis& xrange(const StringView &key, 1571 const StringView &start, 1572 const StringView &end) { 1573 return command(cmd::xrange, key, start, end); 1574 } 1575 xrange(const StringView & key,const StringView & start,const StringView & end,long long count)1576 QueuedRedis& xrange(const StringView &key, 1577 const StringView &start, 1578 const StringView &end, 1579 long long count) { 1580 return command(cmd::xrange, key, start, end, count); 1581 } 1582 xread(const StringView & key,const StringView & id,long long count)1583 QueuedRedis& xread(const StringView &key, const StringView &id, long long count) { 1584 return command(cmd::xread, key, id, count); 1585 } 1586 xread(const StringView & key,const StringView & id)1587 QueuedRedis& xread(const StringView &key, const StringView &id) { 1588 return xread(key, id, 0); 1589 } 1590 1591 template <typename Input> 1592 auto xread(Input first, Input last, long long count) 1593 -> typename std::enable_if<!std::is_convertible<Input, StringView>::value, 1594 QueuedRedis&>::type { 1595 return command(cmd::xread_range<Input>, first, last, count); 1596 } 1597 1598 template <typename Input> 1599 auto xread(Input first, Input last) 1600 -> typename std::enable_if<!std::is_convertible<Input, StringView>::value, 1601 QueuedRedis&>::type { 1602 return xread(first, last, 0); 1603 } 1604 xread(const StringView & key,const StringView & id,const std::chrono::milliseconds & timeout,long long count)1605 QueuedRedis& xread(const StringView &key, 1606 const StringView &id, 1607 const std::chrono::milliseconds &timeout, 1608 long long count) { 1609 return command(cmd::xread_block, key, id, timeout.count(), count); 1610 } 1611 xread(const StringView & key,const StringView & id,const std::chrono::milliseconds & timeout)1612 QueuedRedis& xread(const StringView &key, 1613 const StringView &id, 1614 const std::chrono::milliseconds &timeout) { 1615 return xread(key, id, timeout, 0); 1616 } 1617 1618 template <typename Input> 1619 auto xread(Input first, 1620 Input last, 1621 const std::chrono::milliseconds &timeout, 1622 long long count) 1623 -> typename std::enable_if<!std::is_convertible<Input, StringView>::value, 1624 QueuedRedis&>::type { 1625 return command(cmd::xread_block_range<Input>, first, last, timeout.count(), count); 1626 } 1627 1628 template <typename Input> 1629 auto xread(Input first, 1630 Input last, 1631 const std::chrono::milliseconds &timeout) 1632 -> typename std::enable_if<!std::is_convertible<Input, StringView>::value, 1633 QueuedRedis&>::type { 1634 return xread(first, last, timeout, 0); 1635 } 1636 xreadgroup(const StringView & group,const StringView & consumer,const StringView & key,const StringView & id,long long count,bool noack)1637 QueuedRedis& xreadgroup(const StringView &group, 1638 const StringView &consumer, 1639 const StringView &key, 1640 const StringView &id, 1641 long long count, 1642 bool noack) { 1643 return command(cmd::xreadgroup, group, consumer, key, id, count, noack); 1644 } 1645 xreadgroup(const StringView & group,const StringView & consumer,const StringView & key,const StringView & id,long long count)1646 QueuedRedis& xreadgroup(const StringView &group, 1647 const StringView &consumer, 1648 const StringView &key, 1649 const StringView &id, 1650 long long count) { 1651 return xreadgroup(group, consumer, key, id, count, false); 1652 } 1653 1654 template <typename Input> 1655 auto xreadgroup(const StringView &group, 1656 const StringView &consumer, 1657 Input first, 1658 Input last, 1659 long long count, 1660 bool noack) 1661 -> typename std::enable_if<!std::is_convertible<Input, StringView>::value, 1662 QueuedRedis&>::type { 1663 return command(cmd::xreadgroup_range<Input>, group, consumer, first, last, count, noack); 1664 } 1665 1666 template <typename Input> 1667 auto xreadgroup(const StringView &group, 1668 const StringView &consumer, 1669 Input first, 1670 Input last, 1671 long long count) 1672 -> typename std::enable_if<!std::is_convertible<Input, StringView>::value, 1673 QueuedRedis&>::type { 1674 return xreadgroup(group, consumer, first ,last, count, false); 1675 } 1676 1677 template <typename Input> 1678 auto xreadgroup(const StringView &group, 1679 const StringView &consumer, 1680 Input first, 1681 Input last) 1682 -> typename std::enable_if<!std::is_convertible<Input, StringView>::value, 1683 QueuedRedis&>::type { 1684 return xreadgroup(group, consumer, first ,last, 0, false); 1685 } 1686 xreadgroup(const StringView & group,const StringView & consumer,const StringView & key,const StringView & id,const std::chrono::milliseconds & timeout,long long count,bool noack)1687 QueuedRedis& xreadgroup(const StringView &group, 1688 const StringView &consumer, 1689 const StringView &key, 1690 const StringView &id, 1691 const std::chrono::milliseconds &timeout, 1692 long long count, 1693 bool noack) { 1694 return command(cmd::xreadgroup_block, 1695 group, 1696 consumer, 1697 key, 1698 id, 1699 timeout.count(), 1700 count, 1701 noack); 1702 } 1703 xreadgroup(const StringView & group,const StringView & consumer,const StringView & key,const StringView & id,const std::chrono::milliseconds & timeout,long long count)1704 QueuedRedis& xreadgroup(const StringView &group, 1705 const StringView &consumer, 1706 const StringView &key, 1707 const StringView &id, 1708 const std::chrono::milliseconds &timeout, 1709 long long count) { 1710 return xreadgroup(group, consumer, key, id, timeout, count, false); 1711 } 1712 xreadgroup(const StringView & group,const StringView & consumer,const StringView & key,const StringView & id,const std::chrono::milliseconds & timeout)1713 QueuedRedis& xreadgroup(const StringView &group, 1714 const StringView &consumer, 1715 const StringView &key, 1716 const StringView &id, 1717 const std::chrono::milliseconds &timeout) { 1718 return xreadgroup(group, consumer, key, id, timeout, 0, false); 1719 } 1720 1721 template <typename Input> 1722 auto xreadgroup(const StringView &group, 1723 const StringView &consumer, 1724 Input first, 1725 Input last, 1726 const std::chrono::milliseconds &timeout, 1727 long long count, 1728 bool noack) 1729 -> typename std::enable_if<!std::is_convertible<Input, StringView>::value, 1730 QueuedRedis&>::type { 1731 return command(cmd::xreadgroup_block_range<Input>, 1732 group, 1733 consumer, 1734 first, 1735 last, 1736 timeout.count(), 1737 count, 1738 noack); 1739 } 1740 1741 template <typename Input> 1742 auto xreadgroup(const StringView &group, 1743 const StringView &consumer, 1744 Input first, 1745 Input last, 1746 const std::chrono::milliseconds &timeout, 1747 long long count) 1748 -> typename std::enable_if<!std::is_convertible<Input, StringView>::value, 1749 QueuedRedis&>::type { 1750 return xreadgroup(group, consumer, first, last, timeout, count, false); 1751 } 1752 1753 template <typename Input> 1754 auto xreadgroup(const StringView &group, 1755 const StringView &consumer, 1756 Input first, 1757 Input last, 1758 const std::chrono::milliseconds &timeout) 1759 -> typename std::enable_if<!std::is_convertible<Input, StringView>::value, 1760 QueuedRedis&>::type { 1761 return xreadgroup(group, consumer, first, last, timeout, 0, false); 1762 } 1763 xrevrange(const StringView & key,const StringView & end,const StringView & start)1764 QueuedRedis& xrevrange(const StringView &key, 1765 const StringView &end, 1766 const StringView &start) { 1767 return command(cmd::xrevrange, key, end, start); 1768 } 1769 xrevrange(const StringView & key,const StringView & end,const StringView & start,long long count)1770 QueuedRedis& xrevrange(const StringView &key, 1771 const StringView &end, 1772 const StringView &start, 1773 long long count) { 1774 return command(cmd::xrevrange, key, end, start, count); 1775 } 1776 1777 QueuedRedis& xtrim(const StringView &key, long long count, bool approx = true) { 1778 return command(cmd::xtrim, key, count, approx); 1779 } 1780 1781 private: 1782 friend class Redis; 1783 1784 friend class RedisCluster; 1785 1786 template <typename ...Args> 1787 QueuedRedis(const ConnectionSPtr &connection, Args &&...args); 1788 1789 void _sanity_check() const; 1790 1791 void _reset(); 1792 1793 void _invalidate(); 1794 1795 void _rewrite_replies(std::vector<ReplyUPtr> &replies) const; 1796 1797 template <typename Func> 1798 void _rewrite_replies(const std::vector<std::size_t> &indexes, 1799 Func rewriter, 1800 std::vector<ReplyUPtr> &replies) const; 1801 1802 ConnectionSPtr _connection; 1803 1804 Impl _impl; 1805 1806 std::size_t _cmd_num = 0; 1807 1808 std::vector<std::size_t> _set_cmd_indexes; 1809 1810 std::vector<std::size_t> _georadius_cmd_indexes; 1811 1812 bool _valid = true; 1813 }; 1814 1815 class QueuedReplies { 1816 public: 1817 std::size_t size() const; 1818 1819 redisReply& get(std::size_t idx); 1820 1821 template <typename Result> 1822 Result get(std::size_t idx); 1823 1824 template <typename Output> 1825 void get(std::size_t idx, Output output); 1826 1827 private: 1828 template <typename Impl> 1829 friend class QueuedRedis; 1830 QueuedReplies(std::vector<ReplyUPtr> replies)1831 explicit QueuedReplies(std::vector<ReplyUPtr> replies) : _replies(std::move(replies)) {} 1832 1833 void _index_check(std::size_t idx) const; 1834 1835 std::vector<ReplyUPtr> _replies; 1836 }; 1837 1838 } 1839 1840 } 1841 1842 #include "queued_redis.hpp" 1843 1844 #endif // end SEWENEW_REDISPLUSPLUS_QUEUED_REDIS_H 1845