Skip to content

How to transfer scope for nested async processing on a grandchild thread? #456

Description

@JKomoroski

When my request thread transfers scope to a child thread thread, then that thread thread attempts to transfer the scope to a grandchild thread it is possible to introduce a deadlock.

Here is the most simple example I could make. It doesn't actually create an injector or resolve request scoped objects but the underlying deadlock is the same.

    @Test
    @Timeout(value = 1, threadMode = ThreadMode.SEPARATE_THREAD)
    void testScopeTransferSupplier() throws Exception {
        String a = UUID.randomUUID().toString();

        Supplier<String> supplier = () -> a;

        try (final RequestScoper.CloseableScope ignored = ServletScopes.scopeRequest(Map.of()).open()) {
            final Callable<String> transferred = ServletScopes.transferRequest(supplier::get);
            final Supplier<String> transferredSupplier = () -> {
                try {
                    return transferred.call();
                } catch (RuntimeException e) {
                    throw e;
                } catch (Exception e) {
                    // should not happen, but required since we converted this to a callable
                    throw new CompletionException(e);
                }
            };
            assertEquals(a, CompletableFuture.supplyAsync(transferredSupplier).join());
        }
    }

What are our options when we have nested async calls that require request scoped objects in our application code?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions