123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365 |
- /**************************************************************************
- Copyright (c) 2017 sewenew
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- *************************************************************************/
- #ifndef SEWENEW_REDISPLUSPLUS_REDIS_HPP
- #define SEWENEW_REDISPLUSPLUS_REDIS_HPP
- #include "command.h"
- #include "reply.h"
- #include "utils.h"
- #include "errors.h"
- namespace sw {
- namespace redis {
- template <typename Cmd, typename ...Args>
- auto Redis::command(Cmd cmd, Args &&...args)
- -> typename std::enable_if<!std::is_convertible<Cmd, StringView>::value, ReplyUPtr>::type {
- if (_connection) {
- // Single Connection Mode.
- // TODO: In this case, should we reconnect?
- if (_connection->broken()) {
- throw Error("Connection is broken");
- }
- return _command(*_connection, cmd, std::forward<Args>(args)...);
- } else {
- // Pool Mode, i.e. get connection from pool.
- auto connection = _pool.fetch();
- assert(!connection.broken());
- ConnectionPoolGuard guard(_pool, connection);
- return _command(connection, cmd, std::forward<Args>(args)...);
- }
- }
- template <typename ...Args>
- auto Redis::command(const StringView &cmd_name, Args &&...args)
- -> typename std::enable_if<!IsIter<typename LastType<Args...>::type>::value, ReplyUPtr>::type {
- auto cmd = [](Connection &connection, const StringView &cmd_name, Args &&...args) {
- CmdArgs cmd_args;
- cmd_args.append(cmd_name, std::forward<Args>(args)...);
- connection.send(cmd_args);
- };
- return command(cmd, cmd_name, std::forward<Args>(args)...);
- }
- template <typename Input>
- auto Redis::command(Input first, Input last)
- -> typename std::enable_if<IsIter<Input>::value, ReplyUPtr>::type {
- if (first == last) {
- throw Error("command: empty range");
- }
- auto cmd = [](Connection &connection, Input first, Input last) {
- CmdArgs cmd_args;
- while (first != last) {
- cmd_args.append(*first);
- ++first;
- }
- connection.send(cmd_args);
- };
- return command(cmd, first, last);
- }
- template <typename Result, typename ...Args>
- Result Redis::command(const StringView &cmd_name, Args &&...args) {
- auto r = command(cmd_name, std::forward<Args>(args)...);
- assert(r);
- return reply::parse<Result>(*r);
- }
- template <typename ...Args>
- auto Redis::command(const StringView &cmd_name, Args &&...args)
- -> typename std::enable_if<IsIter<typename LastType<Args...>::type>::value, void>::type {
- auto r = _command(cmd_name,
- MakeIndexSequence<sizeof...(Args) - 1>(),
- std::forward<Args>(args)...);
- assert(r);
- reply::to_array(*r, LastValue(std::forward<Args>(args)...));
- }
- template <typename Result, typename Input>
- auto Redis::command(Input first, Input last)
- -> typename std::enable_if<IsIter<Input>::value, Result>::type {
- auto r = command(first, last);
- assert(r);
- return reply::parse<Result>(*r);
- }
- template <typename Input, typename Output>
- auto Redis::command(Input first, Input last, Output output)
- -> typename std::enable_if<IsIter<Input>::value, void>::type {
- auto r = command(first, last);
- assert(r);
- reply::to_array(*r, output);
- }
- // KEY commands.
- template <typename Input>
- long long Redis::del(Input first, Input last) {
- if (first == last) {
- throw Error("DEL: no key specified");
- }
- auto reply = command(cmd::del_range<Input>, first, last);
- return reply::parse<long long>(*reply);
- }
- template <typename Input>
- long long Redis::exists(Input first, Input last) {
- if (first == last) {
- throw Error("EXISTS: no key specified");
- }
- auto reply = command(cmd::exists_range<Input>, first, last);
- return reply::parse<long long>(*reply);
- }
- inline bool Redis::expire(const StringView &key, const std::chrono::seconds &timeout) {
- return expire(key, timeout.count());
- }
- inline bool Redis::expireat(const StringView &key,
- const std::chrono::time_point<std::chrono::system_clock,
- std::chrono::seconds> &tp) {
- return expireat(key, tp.time_since_epoch().count());
- }
- template <typename Output>
- void Redis::keys(const StringView &pattern, Output output) {
- auto reply = command(cmd::keys, pattern);
- reply::to_array(*reply, output);
- }
- inline bool Redis::pexpire(const StringView &key, const std::chrono::milliseconds &timeout) {
- return pexpire(key, timeout.count());
- }
- inline bool Redis::pexpireat(const StringView &key,
- const std::chrono::time_point<std::chrono::system_clock,
- std::chrono::milliseconds> &tp) {
- return pexpireat(key, tp.time_since_epoch().count());
- }
- inline void Redis::restore(const StringView &key,
- const StringView &val,
- const std::chrono::milliseconds &ttl,
- bool replace) {
- return restore(key, val, ttl.count(), replace);
- }
- template <typename Output>
- long long Redis::scan(long long cursor,
- const StringView &pattern,
- long long count,
- Output output) {
- auto reply = command(cmd::scan, cursor, pattern, count);
- return reply::parse_scan_reply(*reply, output);
- }
- template <typename Output>
- inline long long Redis::scan(long long cursor,
- const StringView &pattern,
- Output output) {
- return scan(cursor, pattern, 10, output);
- }
- template <typename Output>
- inline long long Redis::scan(long long cursor,
- long long count,
- Output output) {
- return scan(cursor, "*", count, output);
- }
- template <typename Output>
- inline long long Redis::scan(long long cursor,
- Output output) {
- return scan(cursor, "*", 10, output);
- }
- template <typename Input>
- long long Redis::touch(Input first, Input last) {
- if (first == last) {
- throw Error("TOUCH: no key specified");
- }
- auto reply = command(cmd::touch_range<Input>, first, last);
- return reply::parse<long long>(*reply);
- }
- template <typename Input>
- long long Redis::unlink(Input first, Input last) {
- if (first == last) {
- throw Error("UNLINK: no key specified");
- }
- auto reply = command(cmd::unlink_range<Input>, first, last);
- return reply::parse<long long>(*reply);
- }
- inline long long Redis::wait(long long numslaves, const std::chrono::milliseconds &timeout) {
- return wait(numslaves, timeout.count());
- }
- // STRING commands.
- template <typename Input>
- long long Redis::bitop(BitOp op, const StringView &destination, Input first, Input last) {
- if (first == last) {
- throw Error("BITOP: no key specified");
- }
- auto reply = command(cmd::bitop_range<Input>, op, destination, first, last);
- return reply::parse<long long>(*reply);
- }
- template <typename Input, typename Output>
- void Redis::mget(Input first, Input last, Output output) {
- if (first == last) {
- throw Error("MGET: no key specified");
- }
- auto reply = command(cmd::mget<Input>, first, last);
- reply::to_array(*reply, output);
- }
- template <typename Input>
- void Redis::mset(Input first, Input last) {
- if (first == last) {
- throw Error("MSET: no key specified");
- }
- auto reply = command(cmd::mset<Input>, first, last);
- reply::parse<void>(*reply);
- }
- template <typename Input>
- bool Redis::msetnx(Input first, Input last) {
- if (first == last) {
- throw Error("MSETNX: no key specified");
- }
- auto reply = command(cmd::msetnx<Input>, first, last);
- return reply::parse<bool>(*reply);
- }
- inline void Redis::psetex(const StringView &key,
- const std::chrono::milliseconds &ttl,
- const StringView &val) {
- return psetex(key, ttl.count(), val);
- }
- inline void Redis::setex(const StringView &key,
- const std::chrono::seconds &ttl,
- const StringView &val) {
- setex(key, ttl.count(), val);
- }
- // LIST commands.
- template <typename Input>
- OptionalStringPair Redis::blpop(Input first, Input last, long long timeout) {
- if (first == last) {
- throw Error("BLPOP: no key specified");
- }
- auto reply = command(cmd::blpop_range<Input>, first, last, timeout);
- return reply::parse<OptionalStringPair>(*reply);
- }
- template <typename Input>
- OptionalStringPair Redis::blpop(Input first,
- Input last,
- const std::chrono::seconds &timeout) {
- return blpop(first, last, timeout.count());
- }
- template <typename Input>
- OptionalStringPair Redis::brpop(Input first, Input last, long long timeout) {
- if (first == last) {
- throw Error("BRPOP: no key specified");
- }
- auto reply = command(cmd::brpop_range<Input>, first, last, timeout);
- return reply::parse<OptionalStringPair>(*reply);
- }
- template <typename Input>
- OptionalStringPair Redis::brpop(Input first,
- Input last,
- const std::chrono::seconds &timeout) {
- return brpop(first, last, timeout.count());
- }
- inline OptionalString Redis::brpoplpush(const StringView &source,
- const StringView &destination,
- const std::chrono::seconds &timeout) {
- return brpoplpush(source, destination, timeout.count());
- }
- template <typename Input>
- inline long long Redis::lpush(const StringView &key, Input first, Input last) {
- if (first == last) {
- throw Error("LPUSH: no key specified");
- }
- auto reply = command(cmd::lpush_range<Input>, key, first, last);
- return reply::parse<long long>(*reply);
- }
- template <typename Output>
- inline void Redis::lrange(const StringView &key, long long start, long long stop, Output output) {
- auto reply = command(cmd::lrange, key, start, stop);
- reply::to_array(*reply, output);
- }
- template <typename Input>
- inline long long Redis::rpush(const StringView &key, Input first, Input last) {
- if (first == last) {
- throw Error("RPUSH: no key specified");
- }
- auto reply = command(cmd::rpush_range<Input>, key, first, last);
- return reply::parse<long long>(*reply);
- }
- // HASH commands.
- template <typename Input>
- inline long long Redis::hdel(const StringView &key, Input first, Input last) {
- if (first == last) {
- throw Error("HDEL: no key specified");
- }
- auto reply = command(cmd::hdel_range<Input>, key, first, last);
- return reply::parse<long long>(*reply);
- }
- template <typename Output>
- inline void Redis::hgetall(const StringView &key, Output output) {
- auto reply = command(cmd::hgetall, key);
- reply::to_array(*reply, output);
- }
- template <typename Output>
- inline void Redis::hkeys(const StringView &key, Output output) {
- auto reply = command(cmd::hkeys, key);
- reply::to_array(*reply, output);
- }
- template <typename Input, typename Output>
- inline void Redis::hmget(const StringView &key, Input first, Input last, Output output) {
- if (first == last) {
- throw Error("HMGET: no key specified");
- }
- auto reply = command(cmd::hmget<Input>, key, first, last);
- reply::to_array(*reply, output);
- }
- template <typename Input>
- inline void Redis::hmset(const StringView &key, Input first, Input last) {
- if (first == last) {
- throw Error("HMSET: no key specified");
- }
- auto reply = command(cmd::hmset<Input>, key, first, last);
- reply::parse<void>(*reply);
- }
- template <typename Output>
- long long Redis::hscan(const StringView &key,
- long long cursor,
- const StringView &pattern,
- long long count,
- Output output) {
- auto reply = command(cmd::hscan, key, cursor, pattern, count);
- return reply::parse_scan_reply(*reply, output);
- }
- template <typename Output>
- inline long long Redis::hscan(const StringView &key,
- long long cursor,
- const StringView &pattern,
- Output output) {
- return hscan(key, cursor, pattern, 10, output);
- }
- template <typename Output>
- inline long long Redis::hscan(const StringView &key,
- long long cursor,
- long long count,
- Output output) {
- return hscan(key, cursor, "*", count, output);
- }
- template <typename Output>
- inline long long Redis::hscan(const StringView &key,
- long long cursor,
- Output output) {
- return hscan(key, cursor, "*", 10, output);
- }
- template <typename Output>
- inline void Redis::hvals(const StringView &key, Output output) {
- auto reply = command(cmd::hvals, key);
- reply::to_array(*reply, output);
- }
- // SET commands.
- template <typename Input>
- long long Redis::sadd(const StringView &key, Input first, Input last) {
- if (first == last) {
- throw Error("SADD: no key specified");
- }
- auto reply = command(cmd::sadd_range<Input>, key, first, last);
- return reply::parse<long long>(*reply);
- }
- template <typename Input, typename Output>
- void Redis::sdiff(Input first, Input last, Output output) {
- if (first == last) {
- throw Error("SDIFF: no key specified");
- }
- auto reply = command(cmd::sdiff<Input>, first, last);
- reply::to_array(*reply, output);
- }
- template <typename Input>
- long long Redis::sdiffstore(const StringView &destination,
- Input first,
- Input last) {
- if (first == last) {
- throw Error("SDIFFSTORE: no key specified");
- }
- auto reply = command(cmd::sdiffstore_range<Input>, destination, first, last);
- return reply::parse<long long>(*reply);
- }
- template <typename Input, typename Output>
- void Redis::sinter(Input first, Input last, Output output) {
- if (first == last) {
- throw Error("SINTER: no key specified");
- }
- auto reply = command(cmd::sinter<Input>, first, last);
- reply::to_array(*reply, output);
- }
- template <typename Input>
- long long Redis::sinterstore(const StringView &destination,
- Input first,
- Input last) {
- if (first == last) {
- throw Error("SINTERSTORE: no key specified");
- }
- auto reply = command(cmd::sinterstore_range<Input>, destination, first, last);
- return reply::parse<long long>(*reply);
- }
- template <typename Output>
- void Redis::smembers(const StringView &key, Output output) {
- auto reply = command(cmd::smembers, key);
- reply::to_array(*reply, output);
- }
- template <typename Output>
- void Redis::spop(const StringView &key, long long count, Output output) {
- auto reply = command(cmd::spop_range, key, count);
- reply::to_array(*reply, output);
- }
- template <typename Output>
- void Redis::srandmember(const StringView &key, long long count, Output output) {
- auto reply = command(cmd::srandmember_range, key, count);
- reply::to_array(*reply, output);
- }
- template <typename Input>
- long long Redis::srem(const StringView &key, Input first, Input last) {
- if (first == last) {
- throw Error("SREM: no key specified");
- }
- auto reply = command(cmd::srem_range<Input>, key, first, last);
- return reply::parse<long long>(*reply);
- }
- template <typename Output>
- long long Redis::sscan(const StringView &key,
- long long cursor,
- const StringView &pattern,
- long long count,
- Output output) {
- auto reply = command(cmd::sscan, key, cursor, pattern, count);
- return reply::parse_scan_reply(*reply, output);
- }
- template <typename Output>
- inline long long Redis::sscan(const StringView &key,
- long long cursor,
- const StringView &pattern,
- Output output) {
- return sscan(key, cursor, pattern, 10, output);
- }
- template <typename Output>
- inline long long Redis::sscan(const StringView &key,
- long long cursor,
- long long count,
- Output output) {
- return sscan(key, cursor, "*", count, output);
- }
- template <typename Output>
- inline long long Redis::sscan(const StringView &key,
- long long cursor,
- Output output) {
- return sscan(key, cursor, "*", 10, output);
- }
- template <typename Input, typename Output>
- void Redis::sunion(Input first, Input last, Output output) {
- if (first == last) {
- throw Error("SUNION: no key specified");
- }
- auto reply = command(cmd::sunion<Input>, first, last);
- reply::to_array(*reply, output);
- }
- template <typename Input>
- long long Redis::sunionstore(const StringView &destination, Input first, Input last) {
- if (first == last) {
- throw Error("SUNIONSTORE: no key specified");
- }
- auto reply = command(cmd::sunionstore_range<Input>, destination, first, last);
- return reply::parse<long long>(*reply);
- }
- // SORTED SET commands.
- inline auto Redis::bzpopmax(const StringView &key, const std::chrono::seconds &timeout)
- -> Optional<std::tuple<std::string, std::string, double>> {
- return bzpopmax(key, timeout.count());
- }
- template <typename Input>
- auto Redis::bzpopmax(Input first, Input last, long long timeout)
- -> Optional<std::tuple<std::string, std::string, double>> {
- auto reply = command(cmd::bzpopmax_range<Input>, first, last, timeout);
- return reply::parse<Optional<std::tuple<std::string, std::string, double>>>(*reply);
- }
- template <typename Input>
- inline auto Redis::bzpopmax(Input first,
- Input last,
- const std::chrono::seconds &timeout)
- -> Optional<std::tuple<std::string, std::string, double>> {
- return bzpopmax(first, last, timeout.count());
- }
- inline auto Redis::bzpopmin(const StringView &key, const std::chrono::seconds &timeout)
- -> Optional<std::tuple<std::string, std::string, double>> {
- return bzpopmin(key, timeout.count());
- }
- template <typename Input>
- auto Redis::bzpopmin(Input first, Input last, long long timeout)
- -> Optional<std::tuple<std::string, std::string, double>> {
- auto reply = command(cmd::bzpopmin_range<Input>, first, last, timeout);
- return reply::parse<Optional<std::tuple<std::string, std::string, double>>>(*reply);
- }
- template <typename Input>
- inline auto Redis::bzpopmin(Input first,
- Input last,
- const std::chrono::seconds &timeout)
- -> Optional<std::tuple<std::string, std::string, double>> {
- return bzpopmin(first, last, timeout.count());
- }
- template <typename Input>
- long long Redis::zadd(const StringView &key,
- Input first,
- Input last,
- UpdateType type,
- bool changed) {
- if (first == last) {
- throw Error("ZADD: no key specified");
- }
- auto reply = command(cmd::zadd_range<Input>, key, first, last, type, changed);
- return reply::parse<long long>(*reply);
- }
- template <typename Interval>
- long long Redis::zcount(const StringView &key, const Interval &interval) {
- auto reply = command(cmd::zcount<Interval>, key, interval);
- return reply::parse<long long>(*reply);
- }
- template <typename Input>
- long long Redis::zinterstore(const StringView &destination,
- Input first,
- Input last,
- Aggregation type) {
- if (first == last) {
- throw Error("ZINTERSTORE: no key specified");
- }
- auto reply = command(cmd::zinterstore_range<Input>,
- destination,
- first,
- last,
- type);
- return reply::parse<long long>(*reply);
- }
- template <typename Interval>
- long long Redis::zlexcount(const StringView &key, const Interval &interval) {
- auto reply = command(cmd::zlexcount<Interval>, key, interval);
- return reply::parse<long long>(*reply);
- }
- template <typename Output>
- void Redis::zpopmax(const StringView &key, long long count, Output output) {
- auto reply = command(cmd::zpopmax, key, count);
- reply::to_array(*reply, output);
- }
- template <typename Output>
- void Redis::zpopmin(const StringView &key, long long count, Output output) {
- auto reply = command(cmd::zpopmin, key, count);
- reply::to_array(*reply, output);
- }
- template <typename Output>
- void Redis::zrange(const StringView &key, long long start, long long stop, Output output) {
- auto reply = _score_command<Output>(cmd::zrange, key, start, stop);
- reply::to_array(*reply, output);
- }
- template <typename Interval, typename Output>
- void Redis::zrangebylex(const StringView &key, const Interval &interval, Output output) {
- zrangebylex(key, interval, {}, output);
- }
- template <typename Interval, typename Output>
- void Redis::zrangebylex(const StringView &key,
- const Interval &interval,
- const LimitOptions &opts,
- Output output) {
- auto reply = command(cmd::zrangebylex<Interval>, key, interval, opts);
- reply::to_array(*reply, output);
- }
- template <typename Interval, typename Output>
- void Redis::zrangebyscore(const StringView &key,
- const Interval &interval,
- Output output) {
- zrangebyscore(key, interval, {}, output);
- }
- template <typename Interval, typename Output>
- void Redis::zrangebyscore(const StringView &key,
- const Interval &interval,
- const LimitOptions &opts,
- Output output) {
- auto reply = _score_command<Output>(cmd::zrangebyscore<Interval>,
- key,
- interval,
- opts);
- reply::to_array(*reply, output);
- }
- template <typename Input>
- long long Redis::zrem(const StringView &key, Input first, Input last) {
- if (first == last) {
- throw Error("ZREM: no key specified");
- }
- auto reply = command(cmd::zrem_range<Input>, key, first, last);
- return reply::parse<long long>(*reply);
- }
- template <typename Interval>
- long long Redis::zremrangebylex(const StringView &key, const Interval &interval) {
- auto reply = command(cmd::zremrangebylex<Interval>, key, interval);
- return reply::parse<long long>(*reply);
- }
- template <typename Interval>
- long long Redis::zremrangebyscore(const StringView &key, const Interval &interval) {
- auto reply = command(cmd::zremrangebyscore<Interval>, key, interval);
- return reply::parse<long long>(*reply);
- }
- template <typename Output>
- void Redis::zrevrange(const StringView &key, long long start, long long stop, Output output) {
- auto reply = _score_command<Output>(cmd::zrevrange, key, start, stop);
- reply::to_array(*reply, output);
- }
- template <typename Interval, typename Output>
- inline void Redis::zrevrangebylex(const StringView &key,
- const Interval &interval,
- Output output) {
- zrevrangebylex(key, interval, {}, output);
- }
- template <typename Interval, typename Output>
- void Redis::zrevrangebylex(const StringView &key,
- const Interval &interval,
- const LimitOptions &opts,
- Output output) {
- auto reply = command(cmd::zrevrangebylex<Interval>, key, interval, opts);
- reply::to_array(*reply, output);
- }
- template <typename Interval, typename Output>
- void Redis::zrevrangebyscore(const StringView &key, const Interval &interval, Output output) {
- zrevrangebyscore(key, interval, {}, output);
- }
- template <typename Interval, typename Output>
- void Redis::zrevrangebyscore(const StringView &key,
- const Interval &interval,
- const LimitOptions &opts,
- Output output) {
- auto reply = _score_command<Output>(cmd::zrevrangebyscore<Interval>, key, interval, opts);
- reply::to_array(*reply, output);
- }
- template <typename Output>
- long long Redis::zscan(const StringView &key,
- long long cursor,
- const StringView &pattern,
- long long count,
- Output output) {
- auto reply = command(cmd::zscan, key, cursor, pattern, count);
- return reply::parse_scan_reply(*reply, output);
- }
- template <typename Output>
- inline long long Redis::zscan(const StringView &key,
- long long cursor,
- const StringView &pattern,
- Output output) {
- return zscan(key, cursor, pattern, 10, output);
- }
- template <typename Output>
- inline long long Redis::zscan(const StringView &key,
- long long cursor,
- long long count,
- Output output) {
- return zscan(key, cursor, "*", count, output);
- }
- template <typename Output>
- inline long long Redis::zscan(const StringView &key,
- long long cursor,
- Output output) {
- return zscan(key, cursor, "*", 10, output);
- }
- template <typename Input>
- long long Redis::zunionstore(const StringView &destination,
- Input first,
- Input last,
- Aggregation type) {
- if (first == last) {
- throw Error("ZUNIONSTORE: no key specified");
- }
- auto reply = command(cmd::zunionstore_range<Input>,
- destination,
- first,
- last,
- type);
- return reply::parse<long long>(*reply);
- }
- // HYPERLOGLOG commands.
- template <typename Input>
- bool Redis::pfadd(const StringView &key, Input first, Input last) {
- if (first == last) {
- throw Error("PFADD: no key specified");
- }
- auto reply = command(cmd::pfadd_range<Input>, key, first, last);
- return reply::parse<bool>(*reply);
- }
- template <typename Input>
- long long Redis::pfcount(Input first, Input last) {
- if (first == last) {
- throw Error("PFCOUNT: no key specified");
- }
- auto reply = command(cmd::pfcount_range<Input>, first, last);
- return reply::parse<long long>(*reply);
- }
- template <typename Input>
- void Redis::pfmerge(const StringView &destination,
- Input first,
- Input last) {
- if (first == last) {
- throw Error("PFMERGE: no key specified");
- }
- auto reply = command(cmd::pfmerge_range<Input>, destination, first, last);
- reply::parse<void>(*reply);
- }
- // GEO commands.
- template <typename Input>
- inline long long Redis::geoadd(const StringView &key,
- Input first,
- Input last) {
- if (first == last) {
- throw Error("GEOADD: no key specified");
- }
- auto reply = command(cmd::geoadd_range<Input>, key, first, last);
- return reply::parse<long long>(*reply);
- }
- template <typename Input, typename Output>
- void Redis::geohash(const StringView &key, Input first, Input last, Output output) {
- if (first == last) {
- throw Error("GEOHASH: no key specified");
- }
- auto reply = command(cmd::geohash_range<Input>, key, first, last);
- reply::to_array(*reply, output);
- }
- template <typename Input, typename Output>
- void Redis::geopos(const StringView &key, Input first, Input last, Output output) {
- if (first == last) {
- throw Error("GEOPOS: no key specified");
- }
- auto reply = command(cmd::geopos_range<Input>, key, first, last);
- reply::to_array(*reply, output);
- }
- template <typename Output>
- void Redis::georadius(const StringView &key,
- const std::pair<double, double> &loc,
- double radius,
- GeoUnit unit,
- long long count,
- bool asc,
- Output output) {
- auto reply = command(cmd::georadius,
- key,
- loc,
- radius,
- unit,
- count,
- asc,
- WithCoord<typename IterType<Output>::type>::value,
- WithDist<typename IterType<Output>::type>::value,
- WithHash<typename IterType<Output>::type>::value);
- reply::to_array(*reply, output);
- }
- template <typename Output>
- void Redis::georadiusbymember(const StringView &key,
- const StringView &member,
- double radius,
- GeoUnit unit,
- long long count,
- bool asc,
- Output output) {
- auto reply = command(cmd::georadiusbymember,
- key,
- member,
- radius,
- unit,
- count,
- asc,
- WithCoord<typename IterType<Output>::type>::value,
- WithDist<typename IterType<Output>::type>::value,
- WithHash<typename IterType<Output>::type>::value);
- reply::to_array(*reply, output);
- }
- // SCRIPTING commands.
- template <typename Result>
- Result Redis::eval(const StringView &script,
- std::initializer_list<StringView> keys,
- std::initializer_list<StringView> args) {
- auto reply = command(cmd::eval, script, keys, args);
- return reply::parse<Result>(*reply);
- }
- template <typename Output>
- void Redis::eval(const StringView &script,
- std::initializer_list<StringView> keys,
- std::initializer_list<StringView> args,
- Output output) {
- auto reply = command(cmd::eval, script, keys, args);
- reply::to_array(*reply, output);
- }
- template <typename Result>
- Result Redis::evalsha(const StringView &script,
- std::initializer_list<StringView> keys,
- std::initializer_list<StringView> args) {
- auto reply = command(cmd::evalsha, script, keys, args);
- return reply::parse<Result>(*reply);
- }
- template <typename Output>
- void Redis::evalsha(const StringView &script,
- std::initializer_list<StringView> keys,
- std::initializer_list<StringView> args,
- Output output) {
- auto reply = command(cmd::evalsha, script, keys, args);
- reply::to_array(*reply, output);
- }
- template <typename Input, typename Output>
- void Redis::script_exists(Input first, Input last, Output output) {
- if (first == last) {
- throw Error("SCRIPT EXISTS: no key specified");
- }
- auto reply = command(cmd::script_exists_range<Input>, first, last);
- reply::to_array(*reply, output);
- }
- // Transaction commands.
- template <typename Input>
- void Redis::watch(Input first, Input last) {
- auto reply = command(cmd::watch_range<Input>, first, last);
- reply::parse<void>(*reply);
- }
- // Stream commands.
- template <typename Input>
- long long Redis::xack(const StringView &key, const StringView &group, Input first, Input last) {
- auto reply = command(cmd::xack_range<Input>, key, group, first, last);
- return reply::parse<long long>(*reply);
- }
- template <typename Input>
- std::string Redis::xadd(const StringView &key, const StringView &id, Input first, Input last) {
- auto reply = command(cmd::xadd_range<Input>, key, id, first, last);
- return reply::parse<std::string>(*reply);
- }
- template <typename Input>
- std::string Redis::xadd(const StringView &key,
- const StringView &id,
- Input first,
- Input last,
- long long count,
- bool approx) {
- auto reply = command(cmd::xadd_maxlen_range<Input>, key, id, first, last, count, approx);
- return reply::parse<std::string>(*reply);
- }
- template <typename Output>
- void Redis::xclaim(const StringView &key,
- const StringView &group,
- const StringView &consumer,
- const std::chrono::milliseconds &min_idle_time,
- const StringView &id,
- Output output) {
- auto reply = command(cmd::xclaim, key, group, consumer, min_idle_time.count(), id);
- reply::to_array(*reply, output);
- }
- template <typename Input, typename Output>
- void Redis::xclaim(const StringView &key,
- const StringView &group,
- const StringView &consumer,
- const std::chrono::milliseconds &min_idle_time,
- Input first,
- Input last,
- Output output) {
- auto reply = command(cmd::xclaim_range<Input>,
- key,
- group,
- consumer,
- min_idle_time.count(),
- first,
- last);
- reply::to_array(*reply, output);
- }
- template <typename Input>
- long long Redis::xdel(const StringView &key, Input first, Input last) {
- auto reply = command(cmd::xdel_range<Input>, key, first, last);
- return reply::parse<long long>(*reply);
- }
- template <typename Output>
- auto Redis::xpending(const StringView &key, const StringView &group, Output output)
- -> std::tuple<long long, OptionalString, OptionalString> {
- auto reply = command(cmd::xpending, key, group);
- return reply::parse_xpending_reply(*reply, output);
- }
- template <typename Output>
- void Redis::xpending(const StringView &key,
- const StringView &group,
- const StringView &start,
- const StringView &end,
- long long count,
- Output output) {
- auto reply = command(cmd::xpending_detail, key, group, start, end, count);
- reply::to_array(*reply, output);
- }
- template <typename Output>
- void Redis::xpending(const StringView &key,
- const StringView &group,
- const StringView &start,
- const StringView &end,
- long long count,
- const StringView &consumer,
- Output output) {
- auto reply = command(cmd::xpending_per_consumer, key, group, start, end, count, consumer);
- reply::to_array(*reply, output);
- }
- template <typename Output>
- void Redis::xrange(const StringView &key,
- const StringView &start,
- const StringView &end,
- Output output) {
- auto reply = command(cmd::xrange, key, start, end);
- reply::to_array(*reply, output);
- }
- template <typename Output>
- void Redis::xrange(const StringView &key,
- const StringView &start,
- const StringView &end,
- long long count,
- Output output) {
- auto reply = command(cmd::xrange_count, key, start, end, count);
- reply::to_array(*reply, output);
- }
- template <typename Output>
- void Redis::xread(const StringView &key,
- const StringView &id,
- long long count,
- Output output) {
- auto reply = command(cmd::xread, key, id, count);
- if (!reply::is_nil(*reply)) {
- reply::to_array(*reply, output);
- }
- }
- template <typename Input, typename Output>
- auto Redis::xread(Input first, Input last, long long count, Output output)
- -> typename std::enable_if<!std::is_convertible<Input, StringView>::value>::type {
- if (first == last) {
- throw Error("XREAD: no key specified");
- }
- auto reply = command(cmd::xread_range<Input>, first, last, count);
- if (!reply::is_nil(*reply)) {
- reply::to_array(*reply, output);
- }
- }
- template <typename Output>
- void Redis::xread(const StringView &key,
- const StringView &id,
- const std::chrono::milliseconds &timeout,
- long long count,
- Output output) {
- auto reply = command(cmd::xread_block, key, id, timeout.count(), count);
- if (!reply::is_nil(*reply)) {
- reply::to_array(*reply, output);
- }
- }
- template <typename Input, typename Output>
- auto Redis::xread(Input first,
- Input last,
- const std::chrono::milliseconds &timeout,
- long long count,
- Output output)
- -> typename std::enable_if<!std::is_convertible<Input, StringView>::value>::type {
- if (first == last) {
- throw Error("XREAD: no key specified");
- }
- auto reply = command(cmd::xread_block_range<Input>, first, last, timeout.count(), count);
- if (!reply::is_nil(*reply)) {
- reply::to_array(*reply, output);
- }
- }
- template <typename Output>
- void Redis::xreadgroup(const StringView &group,
- const StringView &consumer,
- const StringView &key,
- const StringView &id,
- long long count,
- bool noack,
- Output output) {
- auto reply = command(cmd::xreadgroup, group, consumer, key, id, count, noack);
- if (!reply::is_nil(*reply)) {
- reply::to_array(*reply, output);
- }
- }
- template <typename Input, typename Output>
- auto Redis::xreadgroup(const StringView &group,
- const StringView &consumer,
- Input first,
- Input last,
- long long count,
- bool noack,
- Output output)
- -> typename std::enable_if<!std::is_convertible<Input, StringView>::value>::type {
- if (first == last) {
- throw Error("XREADGROUP: no key specified");
- }
- auto reply = command(cmd::xreadgroup_range<Input>, group, consumer, first, last, count, noack);
- if (!reply::is_nil(*reply)) {
- reply::to_array(*reply, output);
- }
- }
- template <typename Output>
- void Redis::xreadgroup(const StringView &group,
- const StringView &consumer,
- const StringView &key,
- const StringView &id,
- const std::chrono::milliseconds &timeout,
- long long count,
- bool noack,
- Output output) {
- auto reply = command(cmd::xreadgroup_block,
- group,
- consumer,
- key,
- id,
- timeout.count(),
- count,
- noack);
- if (!reply::is_nil(*reply)) {
- reply::to_array(*reply, output);
- }
- }
- template <typename Input, typename Output>
- auto Redis::xreadgroup(const StringView &group,
- const StringView &consumer,
- Input first,
- Input last,
- const std::chrono::milliseconds &timeout,
- long long count,
- bool noack,
- Output output)
- -> typename std::enable_if<!std::is_convertible<Input, StringView>::value>::type {
- if (first == last) {
- throw Error("XREADGROUP: no key specified");
- }
- auto reply = command(cmd::xreadgroup_block_range<Input>,
- group,
- consumer,
- first,
- last,
- timeout.count(),
- count,
- noack);
- if (!reply::is_nil(*reply)) {
- reply::to_array(*reply, output);
- }
- }
- template <typename Output>
- void Redis::xrevrange(const StringView &key,
- const StringView &end,
- const StringView &start,
- Output output) {
- auto reply = command(cmd::xrevrange, key, end, start);
- reply::to_array(*reply, output);
- }
- template <typename Output>
- void Redis::xrevrange(const StringView &key,
- const StringView &end,
- const StringView &start,
- long long count,
- Output output) {
- auto reply = command(cmd::xrevrange_count, key, end, start, count);
- reply::to_array(*reply, output);
- }
- template <typename Cmd, typename ...Args>
- ReplyUPtr Redis::_command(Connection &connection, Cmd cmd, Args &&...args) {
- assert(!connection.broken());
- cmd(connection, std::forward<Args>(args)...);
- auto reply = connection.recv();
- return reply;
- }
- template <typename Cmd, typename ...Args>
- inline ReplyUPtr Redis::_score_command(std::true_type, Cmd cmd, Args &&... args) {
- return command(cmd, std::forward<Args>(args)..., true);
- }
- template <typename Cmd, typename ...Args>
- inline ReplyUPtr Redis::_score_command(std::false_type, Cmd cmd, Args &&... args) {
- return command(cmd, std::forward<Args>(args)..., false);
- }
- template <typename Output, typename Cmd, typename ...Args>
- inline ReplyUPtr Redis::_score_command(Cmd cmd, Args &&... args) {
- return _score_command(typename IsKvPairIter<Output>::type(),
- cmd,
- std::forward<Args>(args)...);
- }
- }
- }
- #endif // end SEWENEW_REDISPLUSPLUS_REDIS_HPP
|