aerospike / aerospike-client-java

Aerospike Java Client Library
Other
236 stars 212 forks source link

NioEventLoop prevents main thread completion #142

Closed jrumbinas closed 5 years ago

jrumbinas commented 5 years ago

NioEventLoop is preventing normal Java application exit. Which makes Aerospike incompatible with comman line applications.

public NioEventLoop(EventPolicy policy, SelectorProvider provider, int index) throws IOException {
    super(policy, index);

    commandQueue = new ConcurrentLinkedDeque<Runnable>();
    scheduleQueue = new ArrayDeque<ScheduleTask>(8);
    byteBufferQueue = new ArrayDeque<ByteBuffer>(policy.commandsPerEventLoop);
    selectorTimeout = policy.minTimeout;
    selector = provider.openSelector();

    thread = new Thread(this, "event" + index);
    thread.setDaemon(false);
}
BrianNichols commented 5 years ago

I don't understand. We run netty examples from the command line and they work fine.

cd examples ./run_examples -h \<server hostname> -netty AsyncPutGet

jrumbinas commented 5 years ago

NettyEventLoop != NioEventLoop

jrumbinas commented 5 years ago

FYI https://github.com/aerospike/aerospike-client-java/blob/024c12037a1330087e254a7865fceec28aa2fd15/client/src/com/aerospike/client/async/NioEventLoop.java#L62

BrianNichols commented 5 years ago

Sorry, I misread. NioEventLoop also works fine from the command line:

./run_examples -h \<server hostname> AsyncPutGet

If -netty is not specified, NioEventLoop is used.

jrumbinas commented 5 years ago

Ok, the problem is that we're using Spring exit hooks to close aerospike connections. These hooks are triggered once the main thread exits and there are no more user threads running. The problem is that the second part is never satisfied when NioEventLoop is used. It would be nice to have a configurable option.

BrianNichols commented 5 years ago

You can try setting thread.setDaemon(true); in a custom build to see if that works for your case. Note that active transactions in the event loop will not complete if the event loop is defined as a daemon thread and the application exits.

jrumbinas commented 5 years ago

This also did the trick:

        var threadFactory = new DefaultThreadFactory("aerospike.netty.nio-events", true);
        var group = new NioEventLoopGroup(eventLoopSize, threadFactory);
        return new NettyEventLoops(eventPolicy, group);

Nonetheless, it would still be nice to customize thread names and daemon-ness. I would be happy to submit a pull request if that works for you.

BrianNichols commented 5 years ago

Go ahead and submit a pull request.