redis / lettucemod

Java client for Redis Modules
Apache License 2.0
49 stars 18 forks source link

dumpRegistrations() throws NPE #8

Closed bsbodden closed 3 years ago

bsbodden commented 3 years ago

My deps::

<dependency>
    <groupId>com.redis</groupId>
    <artifactId>spring-lettucemod</artifactId>
    <version>1.6.1</version>
</dependency>

Trying to print the registrations (I can successfully do gears.pyExecute(py); and other commands):

@PostConstruct
public void listRGRegistrations() throws IOException {
  RedisGearsCommands<String, String> gears = connection.sync();
  List<Registration> registrations = gears.dumpRegistrations(); // <== BOOM!
  //...
}

The NPE is:

java.lang.NullPointerException: Cannot invoke "com.redis.lettucemod.gears.Registration.getData()" because "this.registration" is null
bsbodden commented 3 years ago

Can't seem to reproduce it now, closing

bsbodden commented 3 years ago

Full stack trace:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fixedWindowRateLimiterApplication': Invocation of init method failed; nested exception is java.lang.NullPointerException: Cannot invoke "com.redis.lettucemod.gears.Registration.getData()" because "this.registration" is null
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:160) ~[spring-beans-5.3.9.jar:5.3.9]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:422) ~[spring-beans-5.3.9.jar:5.3.9]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1778) ~[spring-beans-5.3.9.jar:5.3.9]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602) ~[spring-beans-5.3.9.jar:5.3.9]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.9.jar:5.3.9]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.9.jar:5.3.9]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.9.jar:5.3.9]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.9.jar:5.3.9]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.9.jar:5.3.9]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.9.jar:5.3.9]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.9.jar:5.3.9]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.9.jar:5.3.9]
    at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.refresh(ReactiveWebServerApplicationContext.java:64) ~[spring-boot-2.5.4.jar:2.5.4]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-2.5.4.jar:2.5.4]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434) ~[spring-boot-2.5.4.jar:2.5.4]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:338) ~[spring-boot-2.5.4.jar:2.5.4]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[spring-boot-2.5.4.jar:2.5.4]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1332) ~[spring-boot-2.5.4.jar:2.5.4]
    at com.redis.rl.FixedWindowRateLimiterApplication.main(FixedWindowRateLimiterApplication.java:99) ~[classes/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.5.4.jar:2.5.4]
Caused by: java.lang.NullPointerException: Cannot invoke "com.redis.lettucemod.gears.Registration.getData()" because "this.registration" is null
    at com.redis.lettucemod.gears.output.RegistrationListOutput.set(RegistrationListOutput.java:69) ~[lettucemod-1.6.1.jar:1.6.1]
    at io.lettuce.core.protocol.RedisStateMachine.safeSet(RedisStateMachine.java:810) ~[lettuce-core-6.1.4.RELEASE.jar:6.1.4.RELEASE]
    at io.lettuce.core.protocol.RedisStateMachine.handleBytes(RedisStateMachine.java:572) ~[lettuce-core-6.1.4.RELEASE.jar:6.1.4.RELEASE]
    at io.lettuce.core.protocol.RedisStateMachine$State$Type.handle(RedisStateMachine.java:206) ~[lettuce-core-6.1.4.RELEASE.jar:6.1.4.RELEASE]
    at io.lettuce.core.protocol.RedisStateMachine.doDecode(RedisStateMachine.java:334) ~[lettuce-core-6.1.4.RELEASE.jar:6.1.4.RELEASE]
    at io.lettuce.core.protocol.RedisStateMachine.decode(RedisStateMachine.java:295) ~[lettuce-core-6.1.4.RELEASE.jar:6.1.4.RELEASE]
    at io.lettuce.core.protocol.CommandHandler.decode(CommandHandler.java:841) ~[lettuce-core-6.1.4.RELEASE.jar:6.1.4.RELEASE]
    at io.lettuce.core.protocol.CommandHandler.decode0(CommandHandler.java:792) ~[lettuce-core-6.1.4.RELEASE.jar:6.1.4.RELEASE]
    at io.lettuce.core.protocol.CommandHandler.decode(CommandHandler.java:775) ~[lettuce-core-6.1.4.RELEASE.jar:6.1.4.RELEASE]
    at io.lettuce.core.protocol.CommandHandler.decode(CommandHandler.java:658) ~[lettuce-core-6.1.4.RELEASE.jar:6.1.4.RELEASE]
    at io.lettuce.core.protocol.CommandHandler.channelRead(CommandHandler.java:598) ~[lettuce-core-6.1.4.RELEASE.jar:6.1.4.RELEASE]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) ~[netty-transport-4.1.67.Final.jar:4.1.67.Final]
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986) ~[netty-common-4.1.67.Final.jar:4.1.67.Final]
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.67.Final.jar:4.1.67.Final]
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.67.Final.jar:4.1.67.Final]
    at java.base/java.lang.Thread.run(Thread.java:832) ~[na:na]
jruaux commented 3 years ago

Can you share what gears commands you ran before dumping registrations?

bsbodden commented 3 years ago

There are no commands executed before the dumpregistrations, goal was to grab and save the registration id in a "registry of gears registrations" at the app level, then only run the registration if needed:

  @PostConstruct
  public void loadGearsScript() throws IOException {
    String py = StreamUtils.copyToString(new ClassPathResource("scripts/rateLimiter.py").getInputStream(),
        Charset.defaultCharset());
    RedisGearsCommands<String, String> gears = connection.sync();
    List<Registration> registrations = gears.dumpRegistrations();
    if (registrations != null) {
      System.out.println(">>> registration count: " + registrations.size());
      for (Registration reg : registrations) {
        System.out.println(">>> registration: " + reg + " == IS A ==> " + reg.getClass().getSimpleName());
      }
    }

    try {
      ExecutionResults er = gears.pyExecute(py);
      if (er != null) {
        System.out.println("IS OK ==> " + er.isOk());
        if (er.getResults() != null) {
          System.out.println(Arrays.toString(er.getResults().toArray()));
        }
      }
    } catch (RedisCommandExecutionException rcee) {
      System.out.println(rcee.getClass().getName());
      System.out.println(rcee.getMessage());
    }

  }
jruaux commented 3 years ago

If possible, can you print the output of RG.DUMPREGISTRATIONS from redis-cli when you encounter the issue?

bsbodden commented 3 years ago

Here's the RG.DUMPREGISTRATIONS:

127.0.0.1:6379> RG.DUMPREGISTRATIONS
1)  1) "id"
    2) "0000000000000000000000000000000000000000-35"
    3) "reader"
    4) "CommandReader"
    5) "desc"
    6) (nil)
    7) "RegistrationData"
    8)  1) "mode"
        2) "async"
        3) "numTriggered"
        4) (integer) 0
        5) "numSuccess"
        6) (integer) 0
        7) "numFailures"
        8) (integer) 0
        9) "numAborted"
       10) (integer) 0
       11) "lastError"
       12) (nil)
       13) "args"
       14) 1) "trigger"
           2) "RateLimiter"
    9) "PD"
   10) "{'sessionId':'0000000000000000000000000000000000000000-17', 'depsList':[]}"
   11) "ExecutionThreadPool"
   12) "DefaultPool"
127.0.0.1:6379>
jruaux commented 3 years ago

This should be fixed in latest snapshot release available at https://s01.oss.sonatype.org/content/repositories/snapshots/