Skip to content

Thread count increased after usage of ScheduledDataLoaderRegistry #173

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

Closed
Ruch12 opened this issue Jan 14, 2025 · 4 comments
Closed

Thread count increased after usage of ScheduledDataLoaderRegistry #173

Ruch12 opened this issue Jan 14, 2025 · 4 comments
Labels

Comments

@Ruch12
Copy link

Ruch12 commented Jan 14, 2025

Describe the bug
We've merged the latest version after validating the fix was deployed - #135 yet the thread count has started to increase significantly. The threads aren't getting closed after the completion of the task unlike DataLoaderRegistry.

We've initialized ScheduledDataLoaderRegistry in the following way in the ServiceContextImpl -

    public ScheduledDataLoaderRegistry getScheduledDataLoaderRegistry() {

        if (null == scheduledDataLoaderRegistry) {
            DispatchPredicate dispatchPredicate = DispatchPredicate.dispatchIfLongerThan(Duration.ofMillis(50));
            scheduledDataLoaderRegistry = ScheduledDataLoaderRegistry.newScheduledRegistry()
                    .registerAll(dataLoaderRegistry)
                    .dispatchPredicate(dispatchPredicate)
                    .build();
        }

        return scheduledDataLoaderRegistry;
    }

The issue is that the threads are not getting closed after the execution of the scheduledDataLoaderRegistry and when the response is ready and sent back.

In this case, shouldn't the logic be handled in a way when there is nothing to be dispatched and all data loaders have completed their work, we should close the thread?

@bbakerman
Copy link
Member

The ScheduledDataLoaderRegistry works in two ways regarding threads or more specifically the ScheduledExecutorService that houses the threads.

You can specify your own executor when you build the ScheduledDataLoaderRegistry as you have shown above or you can use a default ScheduledExecutorService.

If you use the default you must call close on the ScheduledDataLoaderRegistry at the end of the request.

    public void close() {
        closed = true;
        if (defaultExecutorUsed) {
            scheduledExecutorService.shutdown();
        }
    }

In many cases its better to provide your own "shared" ScheduledExecutorService since it wont be created per request.

In this case, shouldn't the logic be handled in a way when there is nothing to be dispatched and all data loaders have completed their work, we should close the thread?

No not really since we cant know when you are finished work... well not truly finished. This is responsibility the using code must take on. You need to call close() on it

@Ruch12
Copy link
Author

Ruch12 commented Jan 15, 2025

Yes, which is what I tried it yesterday of closing the scheduledExecutorService but yet was leading to increase in thread count. I wanted to use the default executor only -

public ScheduledDataLoaderRegistry getScheduledDataLoaderRegistry() {

        if (null == scheduledDataLoaderRegistry) {
            DispatchPredicate dispatchPredicate = DispatchPredicate.dispatchIfLongerThan(Duration.ofMillis(50));
            scheduledDataLoaderRegistry = ScheduledDataLoaderRegistry.newScheduledRegistry()
                    .registerAll(dataLoaderRegistry)
                    .dispatchPredicate(dispatchPredicate)
                    .build();
        }

        return scheduledDataLoaderRegistry;
    }

    /**
     * Experimental change which if doesn't close the threads, will be reverted.
     */
    public void areAllDispatchesComplete(ScheduledDataLoaderRegistry scheduledDataLoaderRegistry) {
        boolean allComplete = true;

        for (DataLoader<?, ?> dataLoader : scheduledDataLoaderRegistry.getDataLoaders()) {
            CompletableFuture<? extends List<?>> dispatchFuture = dataLoader.dispatch();

            if (dispatchFuture.isDone()) {
                try {
                    List<?> futureResults = dispatchFuture.get();

                    for (Object future : futureResults) {
                        if (future instanceof CompletableFuture<?> individualFuture) {
                            if (!individualFuture.isDone()) {
                                allComplete = false;
                                break;
                            }
                        }
                    }
                } catch (InterruptedException | ExecutionException e) {
                    allComplete = false;
                }
            } else {
                allComplete = false;
                break;
            }
        }

        if (allComplete) {
            scheduledDataLoaderRegistry.close();
        }
    }

And now, I'm invoking from my dataloaders function - areAllDispatchesComplete before returning the promise. The thread count is still increasing

Copy link

Hello, this issue has been inactive for 60 days, so we're marking it as stale. If you would like to continue this discussion, please comment within the next 30 days or we'll close the issue.

@github-actions github-actions bot added the Stale label Mar 17, 2025
Copy link

Hello, as this issue has been inactive for 90 days, we're closing the issue. If you would like to resume the discussion, please create a new issue.

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Apr 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants