File tree 11 files changed +78
-18
lines changed
src/main/java/com/linecorp/armeria
reactor3/src/test/java/com/linecorp/armeria/common/reactor3
11 files changed +78
-18
lines changed Original file line number Diff line number Diff line change @@ -139,6 +139,9 @@ dependencies {
139
139
// JUnit Pioneer
140
140
testImplementation libs. junit. pioneer
141
141
142
+ // Reactor for registering EventLoop as a non blocking thread.
143
+ optionalImplementation libs. reactor. core
144
+
142
145
// Reactive Streams
143
146
api libs. reactivestreams
144
147
testImplementation libs. reactivestreams. tck
@@ -217,8 +220,6 @@ if (tasks.findByName('trimShadedJar')) {
217
220
tasks. trimShadedJar. configure {
218
221
// Keep all classes under com.linecorp.armeria, except the internal ones.
219
222
keep " class !com.linecorp.armeria.internal.shaded.**,com.linecorp.armeria.** { *; }"
220
- // Keep the 'NonBlocking' tag interface.
221
- keep " class reactor.core.scheduler.NonBlocking { *; }"
222
223
// Do not optimize the dependencies that access some fields via sun.misc.Unsafe or reflection only.
223
224
keep " class com.linecorp.armeria.internal.shaded.caffeine.** { *; }"
224
225
keep " class com.linecorp.armeria.internal.shaded.jctools.** { *; }"
Original file line number Diff line number Diff line change 36
36
37
37
import com .linecorp .armeria .client .endpoint .EndpointGroup ;
38
38
import com .linecorp .armeria .common .FlagsProvider ;
39
+ import com .linecorp .armeria .common .NonBlocking ;
39
40
import com .linecorp .armeria .common .Scheme ;
40
41
import com .linecorp .armeria .common .SerializationFormat ;
41
42
import com .linecorp .armeria .common .SessionProtocol ;
49
50
import io .micrometer .core .instrument .MeterRegistry ;
50
51
import io .netty .channel .EventLoop ;
51
52
import io .netty .channel .EventLoopGroup ;
52
- import reactor .core .scheduler .NonBlocking ;
53
53
54
54
/**
55
55
* Creates and manages clients.
Original file line number Diff line number Diff line change 47
47
import com .linecorp .armeria .client .proxy .Socks4ProxyConfig ;
48
48
import com .linecorp .armeria .client .proxy .Socks5ProxyConfig ;
49
49
import com .linecorp .armeria .common .ClosedSessionException ;
50
+ import com .linecorp .armeria .common .NonBlocking ;
50
51
import com .linecorp .armeria .common .SerializationFormat ;
51
52
import com .linecorp .armeria .common .SessionProtocol ;
52
53
import com .linecorp .armeria .common .annotation .Nullable ;
76
77
import io .netty .util .AttributeKey ;
77
78
import io .netty .util .concurrent .Future ;
78
79
import io .netty .util .concurrent .Promise ;
79
- import reactor .core .scheduler .NonBlocking ;
80
80
81
81
final class HttpChannelPool implements AsyncCloseable {
82
82
Original file line number Diff line number Diff line change 42
42
import com .linecorp .armeria .client .proxy .ProxyConfigSelector ;
43
43
import com .linecorp .armeria .client .redirect .RedirectConfig ;
44
44
import com .linecorp .armeria .common .Http1HeaderNaming ;
45
+ import com .linecorp .armeria .common .NonBlocking ;
45
46
import com .linecorp .armeria .common .RequestContext ;
46
47
import com .linecorp .armeria .common .Scheme ;
47
48
import com .linecorp .armeria .common .SerializationFormat ;
71
72
import io .netty .handler .ssl .SslContextBuilder ;
72
73
import io .netty .resolver .AddressResolverGroup ;
73
74
import io .netty .util .concurrent .FutureListener ;
74
- import reactor .core .scheduler .NonBlocking ;
75
75
76
76
/**
77
77
* A {@link ClientFactory} that creates an HTTP client.
Original file line number Diff line number Diff line change @@ -41,6 +41,14 @@ public final class CommonPools {
41
41
MoreMeterBinders
42
42
.eventLoopMetrics (WORKER_GROUP , new MeterIdPrefix ("armeria.netty.common" ))
43
43
.bindTo (Flags .meterRegistry ());
44
+
45
+ try {
46
+ Class .forName ("reactor.core.scheduler.Schedulers" ,
47
+ true , CommonPools .class .getClassLoader ());
48
+ ReactorNonBlockingUtil .registerEventLoopAsNonBlocking ();
49
+ } catch (ClassNotFoundException e ) {
50
+ // Do nothing.
51
+ }
44
52
}
45
53
46
54
/**
Original file line number Diff line number Diff line change 30
30
public final class CoreBlockHoundIntegration implements BlockHoundIntegration {
31
31
@ Override
32
32
public void applyTo (Builder builder ) {
33
+ builder .nonBlockingThreadPredicate (predicate -> predicate .or (NonBlocking .class ::isInstance ));
34
+
33
35
// short locks
34
36
builder .allowBlockingCallsInside ("com.linecorp.armeria.client.HttpClientFactory" ,
35
37
"pool" );
Original file line number Diff line number Diff line change 13
13
* License for the specific language governing permissions and limitations
14
14
* under the License.
15
15
*/
16
- package reactor . core . scheduler ;
16
+ package com . linecorp . armeria . common ;
17
17
18
18
/**
19
- * A dummy interface that makes Project Reactor recognize Armeria's event loop threads as non-blocking.
19
+ * An interface that indicates a non-blocking thread. You can use this interface to check if the current
20
+ * thread is a non-blocking thread. For example:
21
+ * <pre>{@code
22
+ * if (Thread.currentThread() instanceof NonBlocking) {
23
+ * // Avoid blocking operations.
24
+ * closeable.closeAsync();
25
+ * } else {
26
+ * closeable.close();
27
+ * }
28
+ * }</pre>
20
29
*/
21
30
public interface NonBlocking {}
Original file line number Diff line number Diff line change 1
1
/*
2
- * Copyright 2019 LINE Corporation
2
+ * Copyright 2024 LINE Corporation
3
3
*
4
4
* LINE Corporation licenses this file to you under the Apache License,
5
5
* version 2.0 (the "License"); you may not use this file except in compliance
13
13
* License for the specific language governing permissions and limitations
14
14
* under the License.
15
15
*/
16
+ package com .linecorp .armeria .common ;
16
17
17
- /**
18
- * Provides a dummy interface that makes Project Reactor recognize Armeria's event loop threads as non-blocking.
19
- */
20
- @ NonNullByDefault
21
- package reactor .core .scheduler ;
18
+ import reactor .core .scheduler .Schedulers ;
19
+
20
+ final class ReactorNonBlockingUtil {
21
+
22
+ static void registerEventLoopAsNonBlocking () {
23
+ Schedulers .registerNonBlockingThreadPredicate (NonBlocking .class ::isInstance );
24
+ }
22
25
23
- import com .linecorp .armeria .common .annotation .NonNullByDefault ;
26
+ private ReactorNonBlockingUtil () {}
27
+ }
Original file line number Diff line number Diff line change 31
31
import com .google .common .collect .MapMaker ;
32
32
33
33
import com .linecorp .armeria .common .Flags ;
34
+ import com .linecorp .armeria .common .NonBlocking ;
34
35
import com .linecorp .armeria .common .annotation .Nullable ;
35
36
36
- import reactor .core .scheduler .NonBlocking ;
37
-
38
37
/**
39
38
* A {@link CompletableFuture} that warns the user if they call a method that blocks the event loop.
40
39
*/
Original file line number Diff line number Diff line change 15
15
*/
16
16
package com .linecorp .armeria .internal .common .util ;
17
17
18
+ import com .linecorp .armeria .common .NonBlocking ;
18
19
import com .linecorp .armeria .common .annotation .Nullable ;
19
20
20
21
import io .netty .util .concurrent .FastThreadLocal ;
21
22
import io .netty .util .concurrent .FastThreadLocalThread ;
22
- import reactor .core .scheduler .NonBlocking ;
23
23
24
24
/**
25
25
* An event loop thread with support for {@link TemporaryThreadLocals}, Netty {@link FastThreadLocal} and
26
- * Project Reactor {@link NonBlocking}.
26
+ * {@link NonBlocking} interface .
27
27
*/
28
28
public final class EventLoopThread extends FastThreadLocalThread implements NonBlocking {
29
29
Original file line number Diff line number Diff line change
1
+ /*
2
+ * Copyright 2024 LINE Corporation
3
+ *
4
+ * LINE Corporation licenses this file to you under the Apache License,
5
+ * version 2.0 (the "License"); you may not use this file except in compliance
6
+ * with the License. You may obtain a copy of the License at:
7
+ *
8
+ * https://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ * License for the specific language governing permissions and limitations
14
+ * under the License.
15
+ */
16
+ package com .linecorp .armeria .common .reactor3 ;
17
+
18
+ import static org .assertj .core .api .Assertions .assertThat ;
19
+
20
+ import org .junit .jupiter .api .Test ;
21
+
22
+ import com .linecorp .armeria .common .CommonPools ;
23
+
24
+ import io .netty .util .concurrent .Future ;
25
+ import reactor .core .scheduler .Schedulers ;
26
+
27
+ final class EventLoopNonBlockingTest {
28
+
29
+ /**
30
+ * Verifies that the current thread is registered a non-blocking thread via {@code ReactorNonBlockingUtil}.
31
+ */
32
+ @ Test
33
+ void checkEventLoopNonBlocking () throws Exception {
34
+ final Future <Boolean > submit = CommonPools .workerGroup ().submit (Schedulers ::isInNonBlockingThread );
35
+ assertThat (submit .get ()).isTrue ();
36
+ }
37
+ }
You can’t perform that action at this time.
0 commit comments