Git Product home page Git Product logo

redis's Introduction

Redis Build Status Hex.pm


Redis commands for Elixir. If you are looking for exredis, please check out exredis branch.



Installation

Add this to the dependencies:

{:redis, "~> 0.1"}

Usage

Redis commands have a few simple types: enums, commands and primitive. Types can be required and optional, multiple and variadic, can be composite.

Situation with required and optional types is simple: required types are just arguments in function and optional values passed with the last argument β€” opts. opts is just a list, opts described in typespecs for each command.

Multiple arguments are arguments that contain one or more values. Multiple arguments can be optional.

Enum types in Redis is just a enumerable (usually), take a look at xx | nx enum:

iex> Redis.set("key", "value", [:xx])
["SET", [" ", "key"], [" ", "value"], [], [" ", "XX"]]

iex> Redis.set("key", "value", [:nx])
["SET", [" ", "key"], [" ", "value"], [], [" ", "NX"]]

Commands are prefixed types, commands can wrap primitive types, enums and composite types:

# command with enum inside
iex> Redis.client_kill(type: :master)
["CLIENT KILL", [], [], [" ", ["TYPE", " ", "master"]], [], []]

# command with primitive type inside
iex> Redis.client_kill(id: "identity")
["CLIENT KILL", [], [" ", ["ID", " ", "identity"]], [], [], []]

# command with composite type inside, inner type of get is: {String.t, integer()}
iex> Redis.bitfield("key", get: {"type", "offset"})
["BITFIELD", [" ", "key"], [" ", ["GET", " ", ["type", " ", "offset"]]], [], [], []]

You can see the usage for every Redis command in IEx:

iex> h Redis.set

  def set(key, value, opts \\ [])

  @spec set(
          key :: key(),
          value :: String.t(),
          opts :: [
            {:expiration, {:ex, :integer} | {:px, :integer}}
            | (:nx | :xx)
            | {:condition, :nx | :xx}
          ]
        ) :: iolist()

since: 1.0.0

Set the string value of a key

Group: string.

Or head to the documentation on hexdocs.


Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

redis's People

Contributors

aforward avatar aidansteele avatar artemeff avatar behe avatar bitdeli-chef avatar courtneycouch avatar davetron5000 avatar drouchy avatar drpandemic avatar frost avatar ignat-z avatar ismaelga avatar jclem avatar joakimk avatar joshuawscott avatar kwojtaszek avatar lastcanal avatar markschmidt avatar mehonoshin avatar mirkoc avatar oivoodoo avatar optimuspaul avatar psli avatar reneklacan avatar rradz avatar rv-bcarter avatar stavro avatar szymon-jez avatar timbuchwaldt avatar whatyouhide avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

redis's Issues

More complete example

Can you provide examples on how to use this in a mix project (supervisor, etc) and not just from the command line. My specific questions are:

  1. how do I pass the connection (client variable) to other modules
  2. where to I instantiate the connection

Hex package has some warnings

I've seen these warnings when downloading and compiling the current hex package for Exredis:

lib/exredis.ex:31: warning: you are piping into a function call without parentheses, which may be ambiguous. Please wrap the function you are piping into in parentheses. For example:

    foo 1 |> bar 2 |> baz 3

Should be written as:

    foo(1) |> bar(2) |> baz(3)

lib/exredis.ex:43: warning: you are piping into a function call without parentheses, which may be ambiguous. Please wrap the function you are piping into in parentheses. For example:

    foo 1 |> bar 2 |> baz 3

Should be written as:

    foo(1) |> bar(2) |> baz(3)

lib/exredis/api.ex:196: warning: you are piping into a function call without parentheses, which may be ambiguous. Please wrap the function you are piping into in parentheses. For example:

    foo 1 |> bar 2 |> baz 3

Should be written as:

    foo(1) |> bar(2) |> baz(3)

I've checked the source code and it seems to be fixed in the last commit, so I guess is a matter of updating the hex package. The problem is you cannot maintain the current version 0.2.3, so it should be 0.2.4.

exredis - ssl and tls support

Hi There,

Thanks for the great work and maintaining the redis library.

We are using exredis and just wondering how it can be configured to support tls/ssl connection. Heroku is using tls/ssl on Redis, and exredis previous configuration cannot connect to the secure Redis instance using the rediss protocol.

Could you please suggest a solution?

HMGET / HMSET example

Hi,

This looks great. I was looking for a good persistence option for Elixir. Are there any examples of HMSET/HMGET with exredis? If not, could you add one?

Thanks,
Kerry

compiled Beam file error

I just tried to pull this library into an app and when I do a mix compile everything is fine, but when I try to use it from the iex terminal I get this:

Interactive Elixir (1.0.5) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> client = ExRedis.sta
22:34:28.115 [error] Loading of /Users/hqmq/code/ultron/_build/dev/lib/exredis/ebin/Elixir.ExRedis.beam failed: :badfile


22:34:28.115 [error] beam/beam_load.c(1250): Error loading module 'Elixir.ExRedis':
  module name in object code is Elixir.Exredis




22:34:30.493 [error] Loading of /Users/hqmq/code/ultron/_build/dev/lib/exredis/ebin/Elixir.ExRedis.beam failed: :badfile


22:34:30.493 [error] beam/beam_load.c(1250): Error loading module 'Elixir.ExRedis':
  module name in object code is Elixir.Exredis



22:34:30.494 [error] Loading of /Users/hqmq/code/ultron/_build/dev/lib/exredis/ebin/Elixir.ExRedis.beam failed: :badfile

** (UndefinedFunctionError) undefined function: ExRedis.sta/0 (module ExRedis is not available)

22:34:30.494 [error] beam/beam_load.c(1250): Error loading module 'Elixir.ExRedis':
  module name in object code is Elixir.Exredis


    ExRedis.sta()

I'm on elixir 1.0.5 (also tried on 1.0.4) and OTP 17.5

Is this a known issue? I tried doing a mix clean and mix compile, but still had the same issue.

Any plan for Scan?

I saw some commented code in Exredis.Api, any plan to implement them?

Publishing Exredis to hex.pm

hex.pm is a very useful hub where you can publish Elixir (and Erlang) packages. It's what Mix dependencies use by default, so if you publish your package to Hex you can then list it as a dependency just as:

[{:exredis, "~> 0.4.0"}]

instead of using the GitHub url. You can also host documentation on Hex (like a lot of packages are doing now) with the mix hex.docs task.

What do you think?

multiple subscription issue

I need to subscribe to a pattern and to a normal channel,
here is my code

client_sub = getRedisSub()
client_sub |> Exredis.Sub.subscribe "status", fn(msg) ->
  case msg do
    {:message, _, groupID, _} -> RedisActions.onSendMessageToMembersOf(groupID)
    _ -> IO.inspect msg
  end
end

client_sub |> Exredis.Sub.psubscribe "message:*", fn(msg) ->
  Message.parse_redis_message(msg)
end

but the problem is only one of them will receive the published events, whichever that comes first.
what am I doing wrong?

Make the client easier to use

I was playing with exredis together with dynamo and noticed some overhead due to the way it handles the connection / the inconvenience of keeping my own instance of the connection.

I would propose registering the PID of the server with Process.register and using it instead of passing in a client everytime. This would lead to only 1 connection + select call, which reduces the load on redis.

What would you say?

Exredis not connecting to the Redis server

I can't get Exredis to connect to the Redis server, neither can I get any of the functions to work. I keep on getting this error when using Exredis.start_using_connection_string("redis://127.0.0.1:6379")

            `{:connection_error, :econnrefused}
        ** (EXIT from #PID<0.391.0>) shell process exited with reason: {:connection_error, :econnrefused}`

And when using

Exredis.Api.set("foo", "bar")

I get this error

** (EXIT from #PID<0.394.0>) shell process exited with reason: an exception was raised: ** (MatchError) no match of right hand side value: {:error, :nxdomain} (eredis) /app/deps/eredis/src/eredis_client.erl:304: :eredis_client.connect/1 (eredis) /app/deps/eredis/src/eredis_client.erl:85: :eredis_client.init/1 (stdlib) gen_server.erl:374: :gen_server.init_it/2 (stdlib) gen_server.erl:342: :gen_server.init_it/6 (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3

I have tried starting it as a child and still nothing has changed. I have configured it on my config.exs as the setup instructions say but there's no change. Anything I may be missing out or any help? I'll really appreciate it. Thanks.

Library evolution

I think this library is done, it has non-idiomatic API with just a few really useful functions, like scripts execution and defredis macro (thank you guys for implementation 🀘).

This library can be more valuable, we need to stop being just a wrapper around eredis and give something better to developers.

Right now I’m writing a module that makes Elixir functions from commands.json file. I’m already done with required and optional arguments, commands (like COUNT and STORE in GEORADIUS), enums (like WITHCOORD, WITHDIST in GEORADIUS) and many other little things. Every generated function has typespecs and documentation. As a result, I want to make this library, like when you don’t want to look at the documentation at all (on redis.io, I mean), just hover at the function in your modern editor :)

redis

The second most important change I want to make β€” rename the library to Redis. Old Exredis code will be in a separate branch and the new library will be published under the new name. With this change, we can test new functionality much faster and give a second wind to it.

Also, I want to make adapters for popular Redis clients (Redix and eredis), to make this library more flexible (but it's in question).

Summarizing:

  • generate Elixir functions from Redis commands.json with docs and typespecs;
  • rename Exredis to Redis;
  • adapters for Redix and eredis?

What do you think?

handling error

Shouldn't we be using {:ok, vaue} and {:error, error} for responses as per elixir/erlang convention?

Multiple connections?

Is it possible to open multiple separate connections with this library? Right now I've got some code that runs a transaction for a HTTP request, but during the time the transaction is open other requests execute Redis commands and they also get queued in the transaction. Is there a way I can open up multiple connections?

Do not provide use ExRedis

If all use ExRedis does is to import functions, then please don't provide it at all. Simply tell users to import ExRedis instead.

The reason is because I always know what import ExRedis does and how to configure it. I have no idea what "use ExRedis" will do and I often assume it does more than simply import.

Redis passwords don't accept spaces

Hello,

I was having problems connecting to my Redis database, always receiving this error:

** (EXIT from #PID<0.163.0>) {:connection_error, {:authentication_error, {:unexpected_data, {:ok, "-ERR wrong number of arguments for 'auth' command\r\n"}}}}

In my Elixir configuration I had:

config :exredis,
  host: "localhost",
  port: 6379,
  password: "Password with spaces.",
  db: 1,
  reconnect: :no_reconnect,
  max_queue: :infinity

To make the library work with my password, I had to change the password field of the configuration to:

(...)
  password: "\"Password with spaces.\"",
(...)

Tracing the bug, I got to the authentication functions in eredis. When I executed the following:

{ok, C} = eredis:start_link("localhost", 6379, 1, "Password with spaces.")

I got:

** exception exit: {connection_error,{authentication_error,{unexpected_data,{ok,<<"-ERR wrong number of arguments for 'auth' command\r\n">>}}}}

I already made a pull request to eredis with a patch to this bug.

Anyway, thank you for the library.

TL;DR: At the moment, eredis is not accepting passwords with spaces and exredis inherits this problem. Earlier this day, I made a pull request to eredis that fixes this bug in eredis, but I am waiting for approval.

Add high-level api

client = Exredis.start

client |> Exredis.set "foo", "bar"
client |> Exredis.get "foo"

undefined function: :eredis.start_link/5

getting this when trying to follow things straight from the README:

iex(2)> Pi.set
** (UndefinedFunctionError) undefined function: :eredis.start_link/5
    :eredis.start_link('127.0.0.1', 6379, 0, [], :no_reconnect)
    lib/exredis.ex:39: Exredis.start/5
    iex:5: Pi.set/0

solved it by adding the dependency for eredis in my own mix.exs file ({ :eredis, "1.0.6", github: "wooga/eredis", ref: "471dd" }) ... not sure if that's an issue with exredis or with me, sorry if it's the latter.

docker: how to configure endpoint of redis server via the System.get_env

I'm having some trouble with configuring where the redis server will be at runtime when running it inside containers, I want to configure it by passing it a connection string like:

client = Exredis.start_using_connection_string(System.get_env("REDIS_PORT_6379_TCP") || "redis://127.0.0.1:6379")

I'm expecting REDIS_PORT_6379_TCP to be "tcp:///123.123.123.123:1234"

but I'm not sure how exactly to do that with elixir (apologies, still learning) I've seen some systems expect these variables in config/config.exs, would that be where they would go?

Cannot connect to server

Not sure if this is a problem with my local box or a bug, but I can't connect to a server using Exredis.start I get a undefined method error:

iex(1)> Exredis.start
** (UndefinedFunctionError) undefined function: :eredis.start_link/5
    :eredis.start_link('127.0.0.1', 6379, 0, [], :no_reconnect)
    lib/exredis.ex:39: Exredis.start/5

Any ideas?

Documentation issues

The first example in the docs has a big problem once used:

defmodule Pi do
  import Exredis

  def get, do: start_link |> elem(1) |> query ["GET", "Pi"]
  def set, do: start_link |> elem(1) |> query ["SET", "Pi", "3.14"]
end
$ redis-cli info|grep connected_clients
connected_clients:141

There should at least be a line of warning that this usage is just an example and noone should really do that (as it piles up connections used just once), also all parameters in piped functions are expected to be in parenthesis.
I will hopefully find time to send a PR later.

Do not promote Exredis.start in the README

Folks should not depend on Exredis.start because it may leave dangling connections. Imagine you are calling Exredis.start inside a GenServer init. Because the processes are not connected, every time the GenServer crashes, you will have a dangling Exredis connection process that will never be reclaimed. We should only promote two ways, really:

  1. Starting Exredis as part of a supervision tree (using start_link)
  2. Starting Exredis using start_link directly

Exredis.Api.incr cannot parse reply as int when used in transaction

When using a transaction, all commands return "QUEUED". Exredis.Api will try to parse that as an integer and fail.

For example, this won't work:

Exredis.Api.multi
Exredis.Api.incr "my_key"
Exredis.Api.exec

My current work-around is:

Exredis.Api.multi
# ... other statements
Exredis.query(Exredis.Api.defaultclient, ["INCR", id])
Exredis.Api.exec

My suggestion would be to not to do auto-parsing at all, but make it clear that you can use these callback functions yourself if you want to. So if you do want to auto-parse, you'd do Exredis.Api.inc "my_key", &Exredis.Api.int_reply/1, and if not, you'd omit the callback function.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.