Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support tuples as keys for get_all/put_all callbacks in Redis/Client cluster #57

Merged
merged 1 commit into from
Jan 7, 2024

Conversation

DanielKulesza
Copy link
Contributor

@DanielKulesza DanielKulesza commented Jan 6, 2024

In the Nebulex README Quickstart example, there are cases where the keys are Elixir tuples.

  @decorate cache_evict(
              cache: Cache,
              keys: [{User, user.id}, {User, user.username}]
            )
  def delete_user(%User{} = user) do
    Repo.delete(user)
  end

Tuples as keys work perfectly fine in nebulex_redis_adapter with a standalone Redis instance. They also work fine with nebulex_redis_adapter in redis_cluster/client_cluster mode for get/put callbacks.

However, get_all and put_all callbacks don't work properly with tuples as keys.
When running those callbacks with tuples as keys, CROSSLOT errors often occur.

Example:

 1) test MOVED put and get operations with tuple keys (NebulexRedisAdapter.RedisClusterTest)
     test/nebulex_redis_adapter/redis_cluster_test.exs:188
     ** (Redix.Error) CROSSSLOT Keys in request don't hash to the same slot
     code: assert Cache.get_all([{RedisCache.Testing, "key1"}, {RedisCache.Testing, "key2"}]) == %{
     stacktrace:
       (nebulex_redis_adapter 2.3.1) lib/nebulex_redis_adapter/command.ex:167: NebulexRedisAdapter.Command.handle_command_response/2
       (nebulex_redis_adapter 2.3.1) lib/nebulex_redis_adapter.ex:559: NebulexRedisAdapter.mget/4
       (nebulex_redis_adapter 2.3.1) lib/nebulex_redis_adapter.ex:542: anonymous fn/4 in NebulexRedisAdapter.do_get_all/3
       (stdlib 3.17.2.1) maps.erl:410: :maps.fold_1/3
       (nebulex_redis_adapter 2.3.1) lib/nebulex_redis_adapter.ex:530: anonymous fn/4 in NebulexRedisAdapter.get_all/3
       (telemetry 1.2.1) /Users/Daniel.Kulesza/Projects/nebulex_redis_adapter/deps/telemetry/src/telemetry.erl:321: :telemetry.span/3
       test/nebulex_redis_adapter/redis_cluster_test.exs:194: (test)

This appears because the group_keys_by_hash_slot function takes an Enum.t() of:

  • any values as keys when grouping keys for a get_all
    OR
  • tuples of key-value pairs when grouping keys for a put_all

The change in this Pull Request aims to resolve this issue by specifying an atom (:keys/:tuples) as an argument to differentiate between the two cases.

@cabol
Copy link
Owner

cabol commented Jan 7, 2024

Nice! Thanks for the fix!

@cabol cabol merged commit eb211f3 into cabol:master Jan 7, 2024
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants