Azure / azure-sdk-for-java

This repository is for active development of the Azure SDK for Java. For consumers of the SDK we recommend visiting our public developer docs at https://docs.microsoft.com/java/azure/ or our versioned developer docs at https://azure.github.io/azure-sdk-for-java.
MIT License
2.25k stars 1.93k forks source link

[BUG] Error while trying to publish events using Event Grid's publishCloudEvent (sync) and using jar 4.17.0-beta.1 #37039

Open 1-javier-fernandez opened 9 months ago

1-javier-fernandez commented 9 months ago

Describe the bug The following root cause exception is thrown when attempting to publish an event using Event Grid's synchronous EventGridClient.publishCloudEvent in a SpringBoot 2.7.3 application:

java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-epoll-2

Note: the same code works as expected using a project with just the azure-messaging-eventgrid and azure-core dependencies.

Exception or Stack Trace

Stack trace is too long. I have attached it.

To Reproduce

Create a Spring Boot application version 2.7.3 that uses Event Grid's 4.17.0-beta.1 jar. Then use code like in the coming section.

Code Snippet

    public static final String TOPICNAME = "jfgTpc1";
    public static final String EVENT_SUBSCRIPTION_NAME = "evtsub1";
    public static final String ENDPOINT = "";  // namespace endpoint
    public static final AzureKeyCredential CREDENTIAL = new AzureKeyCredential("<key for namespace  http endpoint>");

    public void publishCloudEventSync() {
        EventGridClient client = buildClient();
        PublishResult publishResult = client.publishCloudEvent(TOPICNAME, getCloudEvent());
    }

    EventGridClient buildClient() {
        return buildClientBuilder().buildClient();
    }

    EventGridAsyncClient buildAsyncClient() {
        return buildClientBuilder().buildAsyncClient();
    }

    EventGridClientBuilder buildClientBuilder() {
        return new EventGridClientBuilder()
                .httpClient(HttpClient.createDefault())
                .endpoint(ENDPOINT)
                .serviceVersion(EventGridMessagingServiceVersion.V2023_06_01_PREVIEW)
                .credential(CREDENTIAL);
    }

    private static CloudEvent getCloudEvent() {
        return new CloudEvent("/events/testEvent", "Microsoft.MockPublisher.TestEvent",
                BinaryData.fromObject(new HashMap<String, String>() {
                    {
                        put("Field1", "Value1");
                        put("Field2", "Value2");
                        put("Field3", "Value3");
                    }
                }), CloudEventDataFormat.JSON, "application/json")
                .setSubject("Test")
                .setTime(OffsetDateTime.now());
    }

Expected behavior The code should send 1 event to the namespace topic configured. You should be able to see on the namespace's metrics (Azure portal and on the namespace overview page) that event(s) have been published successfully.

Screenshots N/A

Setup (please complete the following information):

Additional context

Information Checklist Kindly make sure that you have added all the following information above and checkoff the required fields otherwise we will treat the issuer as an incomplete report

1-javier-fernandez commented 9 months ago

You may tag me by also using @jfggdl (I am the Event Grid Product Manager).

1-javier-fernandez commented 9 months ago

stack trace.txt

1-javier-fernandez commented 9 months ago

simple-project-that-works-left-vs-my-project-dependencies-right.pdf

1-javier-fernandez commented 9 months ago

I have added a comparison report that shows the dependencies of a simple project that depends only on the messaging.eventgrid jar, which it works as expected, vs my project's dependencies. There are minor version changes between the two set of dependencies where they have common jars.

billwert commented 9 months ago

@saragluna FYI - I will take a first look but if you see something that jumps out please speak up! :)

anuchandy commented 9 months ago

@billwert - Just sharing some thoughts. One possibility is, the call site of publishCloudEventSync() happens to run on Netty-IO thread. For example, if call site is a callback that Netty-Server calls upon the arrival HTTP request (mapped to some REST Path).

If the SDK sync API (sync over async) underneath blocks the current thread and given the current thread is IO Thread, setup may emit this error.

If that’s the case, I wonder in general if Spring has some way / annotation to set a block-able worker Thread to run the publishCloudEventSync() or configure that Netty callback runs on block-able worker Thread. @saragluna

saragluna commented 9 months ago

@1-javier-fernandez I am wondering how is the publishCloudEventSync() method called in your project? Do you have the codesnippet for that?

jfggdl commented 8 months ago

@saragluna It is exactly the code pasted on the top when I created the issue. Thanks for looking into this.

saragluna commented 8 months ago

Hi @jfggdl, but the publishCloudEventSync needs to be called, maybe by a controller?

jfggdl commented 8 months ago

@saragluna, Correct. It is a simple call to the publishCloudEventSync() from a controller method using jar 4.17.0-beta.1.

jfggdl commented 8 months ago

@saragluna do we have an ETA as to when this issue should be mitigated? Thanks. This is Javier from Event Grid, by the way. You may want to ping me in Teams to get my attention immediately.