eed3si9n / gigahorse

Gigahorse is an HTTP client for Scala with multiple backend support.
http://eed3si9n.com/gigahorse
Apache License 2.0
121 stars 25 forks source link

Compile-time Usage Problems #20

Open darkfrog26 opened 7 years ago

darkfrog26 commented 7 years ago

I'm using Gigahorse (asynchttpclient) in a compile-time Macro to connect to a database to validate database queries and this works, but after the code runs I get a bunch of:

Exception in thread "AsyncHttpClient-2-1" java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$1
        at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:435)
        at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:102)
        at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:179)
        at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:144)
        at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: io.netty.util.concurrent.DefaultPromise$1
        at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        ... 5 more

In the output in SBT. Is Jetty just not happy running at compile-time? I'm not sure if this is a bug with Gigahorse or something I'm missing, but I'd prefer not to have to switch to the Akka version if possible.

darkfrog26 commented 7 years ago

Okay, I think I've figured out the problem. It looks as though as soon as the Macro completes there's still "cleanup" that Netty tries to do, but the compiler seems to be unloading or stop allowing the loading of classes so these errors are thrown asynchronously. If I add a Thread.sleep(...) after my Macro to give time for Netty to notifyListeners then no errors are thrown and everything works as it should.

This, however, creates a scenario where Gigahorse should allow some sort of synchronous "dispose" method to wait for the underlying implementation to cleanup before I release back to the compiler.

@eed3si9n let me know if you need any additional information on this. This problem is holding me up on a project I'm working on, so I'm eager to get a resolution ASAP.

eed3si9n commented 7 years ago

This, however, creates a scenario where Gigahorse should allow some sort of synchronous "dispose" method to wait for the underlying implementation to cleanup before I release back to the compiler.

That's the purpose of Gigahorse.withHttp.

darkfrog26 commented 7 years ago

Though I'm not using withHttp because I want to return a Future, I am using onComplete to close the connection. Is this my problem? Is onComplete running asynchronously after the Future completes?

Here's the code: https://github.com/outr/arangodb-scala/blob/master/src/main/scala/com/outr/arango/ArangoDB.scala#L42

darkfrog26 commented 7 years ago

I tried adding:

 andThen {
      case t => {
        http.close()
        t
      }
    }

to my returned Future but the exceptions still fire.

eed3si9n commented 7 years ago

Future is only as good as its holder. If you want to rein in the runaway Netty, then you have to hold on to http and close it somewhere you can predict.