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

Configurable prefix for redis key #121

Open
sizzle168 opened this issue Nov 1, 2023 · 6 comments
Open

Configurable prefix for redis key #121

sizzle168 opened this issue Nov 1, 2023 · 6 comments

Comments

@sizzle168
Copy link

Hey,

thanks for providing this useful package. I was wondering if there is a way to configure a prefix for the redis key? Currently, it could lead to problems if several applications share the same redis database.

Thanks in advance.

@cristipufu
Copy link
Owner

Hi @sizzle168,

Yes, you can configure a prefix for the redis key, here's a related issue: #93

@sizzle168
Copy link
Author

sizzle168 commented Nov 13, 2023

@cristipufu
Thank's for your answer. Actually I meant a prefix for the whole key. Looking at https://github.com/cristipufu/aspnetcore-redis-rate-limiting/blob/master/src/RedisRateLimiting/FixedWindow/RedisFixedWindowManager.cs, it doesn't seem to be possible or is there any other way?

RateLimitKey = new RedisKey($"rl:{{{partitionKey}}}");

I need a prefix before "rl:"

@cristipufu
Copy link
Owner

You can play around with partitionKey - does it have to be before "rl:"?

@cristipufu cristipufu reopened this Nov 13, 2023
@sizzle168
Copy link
Author

sizzle168 commented Nov 13, 2023

That wouldn't be that helpful. We have different applications running on the same redis db with a app-specific redis key-prefix and I would want to put that rate limit values under the prefix of our app.

@cristipufu
Copy link
Owner

You can do something like:

return RedisRateLimitPartition.GetFixedWindowRateLimiter($"{appName}", _ =>
               new RedisFixedWindowRateLimiterOptions
               {
                   ConnectionMultiplexerFactory = () => connectionMultiplexer,
                   PermitLimit = 2,
                   Window = TimeSpan.FromSeconds(1)                                   
               });

The key in Redis would be "rl:{appName}"

@hacst
Copy link
Contributor

hacst commented Dec 15, 2023

Recently I was also searching for an option to easily add prefixes. Though in my case it was for parallel test execution with a real redis during integration tests. There is WithKeyPrefix on the IDatabase but that doesn't work for something that wants a multiplexer factory. Adjusting part of the partition key for this was definitely a possibility. However in the end I went with creating a DispatchProxy for IConnectionMultiplexer that uses WithKeyPrefix on each IDatabase returned by GetDatabase. That way everything using the factory, including the rate limiters, always uses the prefix and I don't have to figure out how to do it for everything that uses redis. In case it is helpful to someone:

  public static class IConnectionMultiplexerExtensions
  {
    public static IConnectionMultiplexer WithKeyPrefix(this IConnectionMultiplexer multiplexer, string prefix)
    {
      if (String.IsNullOrEmpty(prefix)) {
        return multiplexer;
      }
      return GetDatabaseWithKeyPrefixProxy.Decorate(multiplexer, prefix);
    }

    private class GetDatabaseWithKeyPrefixProxy : DispatchProxy
    {
      public string? Prefix { get; private set; }
      public IConnectionMultiplexer? Target { get; private set; }
      protected override object? Invoke(MethodInfo? targetMethod, object?[]? args)
      {
        if (targetMethod?.Name == nameof(IConnectionMultiplexer.GetDatabase)) {
          return ((IDatabase?)targetMethod?.Invoke(Target, args))?.WithKeyPrefix(Prefix);
        }
        return targetMethod?.Invoke(Target, args);
      }

      public static IConnectionMultiplexer Decorate(IConnectionMultiplexer multi, String prefix)
      {
        var proxy = (Create<IConnectionMultiplexer, GetDatabaseWithKeyPrefixProxy>() as GetDatabaseWithKeyPrefixProxy)!;
        proxy.Target = multi;
        proxy.Prefix = prefix;
        return (proxy as IConnectionMultiplexer)!;
      }
    }
  }

It works just fine for me but I only use it for tests. I imagine due to the dynamic nature of this and the breadth of IConnectionMultiplexer there might be cases where this breaks down.

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

No branches or pull requests

3 participants