You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2022/04/30 04:12:34 UTC
[james-project] branch master updated (cea45a4598 -> 98b53e6439)
This is an automated email from the ASF dual-hosted git repository.
btellier pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
from cea45a4598 JAMES-3753 Rewrite FlowedMessageUtils.flow()
new c00eba46a8 JAMES-3752 - Enable ImapHeartbeatHandler by setting idle time interval
new 98b53e6439 JAMES-3752 Allow disabling ImapChannelUpstreamHandler heartbeat handler
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../apache/james/imap/api/ImapConfiguration.java | 5 ++
.../apache/james/imap/processor/IdleProcessor.java | 2 +-
.../docs/modules/ROOT/pages/configure/imap.adoc | 2 +
.../apache/james/imapserver/netty/IMAPServer.java | 11 +++-
.../netty/ImapChannelUpstreamHandler.java | 63 +++++++++++++++-------
.../src/main/resources/imapserver.xml | 3 ++
src/site/xdoc/server/config-imap4.xml | 2 +
7 files changed, 65 insertions(+), 23 deletions(-)
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 01/02: JAMES-3752 - Enable ImapHeartbeatHandler by setting idle time interval
Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit c00eba46a81a44e95e3a6c63b2cd57b9a8791949
Author: Tung Van TRAN <vt...@linagora.com>
AuthorDate: Mon Apr 18 16:32:04 2022 +0700
JAMES-3752 - Enable ImapHeartbeatHandler by setting idle time interval
---
.../java/org/apache/james/imap/api/ImapConfiguration.java | 5 +++++
.../org/apache/james/imap/processor/IdleProcessor.java | 2 +-
.../org/apache/james/imapserver/netty/IMAPServer.java | 8 ++++++--
.../imapserver/netty/ImapChannelUpstreamHandler.java | 15 ++++++++++++---
4 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/api/ImapConfiguration.java b/protocols/imap/src/main/java/org/apache/james/imap/api/ImapConfiguration.java
index 962f7f53b6..4db594d3d7 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/api/ImapConfiguration.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/api/ImapConfiguration.java
@@ -19,6 +19,7 @@
package org.apache.james.imap.api;
+import java.time.Duration;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
@@ -145,6 +146,10 @@ public class ImapConfiguration {
return isCondstoreEnable;
}
+ public Duration idleTimeIntervalAsDuration() {
+ return Duration.of(getIdleTimeInterval(), getIdleTimeIntervalUnit().toChronoUnit());
+ }
+
@Override
public final boolean equals(Object obj) {
if (obj instanceof ImapConfiguration) {
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/IdleProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/IdleProcessor.java
index 28895174b2..39005f0020 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/IdleProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/IdleProcessor.java
@@ -69,7 +69,7 @@ public class IdleProcessor extends AbstractMailboxProcessor<IdleRequest> impleme
public void configure(ImapConfiguration imapConfiguration) {
super.configure(imapConfiguration);
- this.heartbeatInterval = Duration.of(imapConfiguration.getIdleTimeInterval(), imapConfiguration.getIdleTimeIntervalUnit().toChronoUnit());
+ this.heartbeatInterval = imapConfiguration.idleTimeIntervalAsDuration();
this.enableIdle = imapConfiguration.isEnableIdle();
}
diff --git a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
index 5082d59015..d2a8e2fe1a 100644
--- a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
+++ b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
@@ -19,6 +19,7 @@
package org.apache.james.imapserver.netty;
import java.net.MalformedURLException;
+import java.time.Duration;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
@@ -134,6 +135,7 @@ public class IMAPServer extends AbstractConfigurableAsyncServer implements ImapC
private AuthenticationConfiguration authenticationConfiguration;
private Optional<ConnectionLimitUpstreamHandler> connectionLimitUpstreamHandler = Optional.empty();
private Optional<ConnectionPerIpLimitUpstreamHandler> connectionPerIpLimitUpstreamHandler = Optional.empty();
+ private Duration heartbeatInterval;
public static final int DEFAULT_MAX_LINE_LENGTH = 65536; // Use a big default
public static final Size DEFAULT_IN_MEMORY_SIZE_LIMIT = Size.of(10L, Size.Unit.M); // Use 10MB as default
@@ -172,8 +174,9 @@ public class IMAPServer extends AbstractConfigurableAsyncServer implements ImapC
authenticationConfiguration = AuthenticationConfiguration.parse(configuration);
connectionLimitUpstreamHandler = ConnectionLimitUpstreamHandler.forCount(connectionLimit);
connectionPerIpLimitUpstreamHandler = ConnectionPerIpLimitUpstreamHandler.forCount(connPerIP);
-
- processor.configure(getImapConfiguration(configuration));
+ ImapConfiguration imapConfiguration = getImapConfiguration(configuration);
+ heartbeatInterval = imapConfiguration.idleTimeIntervalAsDuration();
+ processor.configure(imapConfiguration);
}
@VisibleForTesting static ImapConfiguration getImapConfiguration(HierarchicalConfiguration<ImmutableNode> configuration) {
@@ -262,6 +265,7 @@ public class IMAPServer extends AbstractConfigurableAsyncServer implements ImapC
.authenticationConfiguration(authenticationConfiguration)
.secure(secure)
.imapMetrics(imapMetrics)
+ .heartbeatInterval(heartbeatInterval)
.build();
}
diff --git a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapChannelUpstreamHandler.java b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapChannelUpstreamHandler.java
index 137f4ec30c..f4271d959a 100644
--- a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapChannelUpstreamHandler.java
+++ b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapChannelUpstreamHandler.java
@@ -23,6 +23,7 @@ import static org.apache.james.imapserver.netty.IMAPServer.AuthenticationConfigu
import java.io.Closeable;
import java.io.IOException;
import java.net.InetSocketAddress;
+import java.time.Duration;
import java.util.NoSuchElementException;
import java.util.Optional;
@@ -71,6 +72,7 @@ public class ImapChannelUpstreamHandler extends ChannelInboundHandlerAdapter imp
private ImapEncoder encoder;
private IMAPServer.AuthenticationConfiguration authenticationConfiguration;
private ImapMetrics imapMetrics;
+ private Duration heartbeatInterval;
public ImapChannelUpstreamHandlerBuilder hello(String hello) {
this.hello = hello;
@@ -107,8 +109,13 @@ public class ImapChannelUpstreamHandler extends ChannelInboundHandlerAdapter imp
return this;
}
+ public ImapChannelUpstreamHandlerBuilder heartbeatInterval(Duration heartbeatInterval) {
+ this.heartbeatInterval = heartbeatInterval;
+ return this;
+ }
+
public ImapChannelUpstreamHandler build() {
- return new ImapChannelUpstreamHandler(hello, processor, encoder, compress, secure, imapMetrics, authenticationConfiguration);
+ return new ImapChannelUpstreamHandler(hello, processor, encoder, compress, secure, imapMetrics, authenticationConfiguration, (int) heartbeatInterval.toSeconds());
}
}
@@ -126,7 +133,7 @@ public class ImapChannelUpstreamHandler extends ChannelInboundHandlerAdapter imp
private final ImapEncoder encoder;
- private final ImapHeartbeatHandler heartbeatHandler = new ImapHeartbeatHandler(0,0,0);
+ private final ImapHeartbeatHandler heartbeatHandler;
private final AuthenticationConfiguration authenticationConfiguration;
@@ -135,7 +142,8 @@ public class ImapChannelUpstreamHandler extends ChannelInboundHandlerAdapter imp
private final Metric imapCommandsMetric;
public ImapChannelUpstreamHandler(String hello, ImapProcessor processor, ImapEncoder encoder, boolean compress,
- Encryption secure, ImapMetrics imapMetrics, AuthenticationConfiguration authenticationConfiguration) {
+ Encryption secure, ImapMetrics imapMetrics, AuthenticationConfiguration authenticationConfiguration,
+ int heartbeatIntervalSeconds) {
this.hello = hello;
this.processor = processor;
this.encoder = encoder;
@@ -144,6 +152,7 @@ public class ImapChannelUpstreamHandler extends ChannelInboundHandlerAdapter imp
this.authenticationConfiguration = authenticationConfiguration;
this.imapConnectionsMetric = imapMetrics.getConnectionsMetric();
this.imapCommandsMetric = imapMetrics.getCommandsMetric();
+ this.heartbeatHandler = new ImapHeartbeatHandler(heartbeatIntervalSeconds, heartbeatIntervalSeconds, heartbeatIntervalSeconds);
}
@Override
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 02/02: JAMES-3752 Allow disabling ImapChannelUpstreamHandler heartbeat handler
Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 98b53e64398e57f1fcf9fa39b1fd81f056fd6859
Author: Tung Van TRAN <vt...@linagora.com>
AuthorDate: Mon Apr 18 16:27:34 2022 +0700
JAMES-3752 Allow disabling ImapChannelUpstreamHandler heartbeat handler
---
.../docs/modules/ROOT/pages/configure/imap.adoc | 2 +
.../apache/james/imapserver/netty/IMAPServer.java | 3 ++
.../netty/ImapChannelUpstreamHandler.java | 52 ++++++++++++++--------
.../src/main/resources/imapserver.xml | 3 ++
src/site/xdoc/server/config-imap4.xml | 2 +
5 files changed, 43 insertions(+), 19 deletions(-)
diff --git a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/imap.adoc b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/imap.adoc
index 57adb3523a..fc60ea4ce0 100644
--- a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/imap.adoc
+++ b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/imap.adoc
@@ -107,6 +107,8 @@ will use the specified value.
| connectionLimitPerIP
| Set the maximum simultaneous incoming connections per IP for this service
+| ignoreIDLEUponProcessing
+| true or false - Allow disabling the heartbeat handler. Defaults to true.
|===
== OIDC setup
diff --git a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
index d2a8e2fe1a..b220446912 100644
--- a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
+++ b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
@@ -135,6 +135,7 @@ public class IMAPServer extends AbstractConfigurableAsyncServer implements ImapC
private AuthenticationConfiguration authenticationConfiguration;
private Optional<ConnectionLimitUpstreamHandler> connectionLimitUpstreamHandler = Optional.empty();
private Optional<ConnectionPerIpLimitUpstreamHandler> connectionPerIpLimitUpstreamHandler = Optional.empty();
+ private boolean ignoreIDLEUponProcessing;
private Duration heartbeatInterval;
public static final int DEFAULT_MAX_LINE_LENGTH = 65536; // Use a big default
@@ -174,6 +175,7 @@ public class IMAPServer extends AbstractConfigurableAsyncServer implements ImapC
authenticationConfiguration = AuthenticationConfiguration.parse(configuration);
connectionLimitUpstreamHandler = ConnectionLimitUpstreamHandler.forCount(connectionLimit);
connectionPerIpLimitUpstreamHandler = ConnectionPerIpLimitUpstreamHandler.forCount(connPerIP);
+ ignoreIDLEUponProcessing = configuration.getBoolean("ignoreIDLEUponProcessing", true);
ImapConfiguration imapConfiguration = getImapConfiguration(configuration);
heartbeatInterval = imapConfiguration.idleTimeIntervalAsDuration();
processor.configure(imapConfiguration);
@@ -266,6 +268,7 @@ public class IMAPServer extends AbstractConfigurableAsyncServer implements ImapC
.secure(secure)
.imapMetrics(imapMetrics)
.heartbeatInterval(heartbeatInterval)
+ .ignoreIDLEUponProcessing(ignoreIDLEUponProcessing)
.build();
}
diff --git a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapChannelUpstreamHandler.java b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapChannelUpstreamHandler.java
index f4271d959a..4e3515e45f 100644
--- a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapChannelUpstreamHandler.java
+++ b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapChannelUpstreamHandler.java
@@ -52,7 +52,6 @@ import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
-import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.TooLongFrameException;
import reactor.core.publisher.Mono;
@@ -72,6 +71,7 @@ public class ImapChannelUpstreamHandler extends ChannelInboundHandlerAdapter imp
private ImapEncoder encoder;
private IMAPServer.AuthenticationConfiguration authenticationConfiguration;
private ImapMetrics imapMetrics;
+ private boolean ignoreIDLEUponProcessing;
private Duration heartbeatInterval;
public ImapChannelUpstreamHandlerBuilder hello(String hello) {
@@ -109,13 +109,18 @@ public class ImapChannelUpstreamHandler extends ChannelInboundHandlerAdapter imp
return this;
}
+ public ImapChannelUpstreamHandlerBuilder ignoreIDLEUponProcessing(boolean ignoreIDLEUponProcessing) {
+ this.ignoreIDLEUponProcessing = ignoreIDLEUponProcessing;
+ return this;
+ }
+
public ImapChannelUpstreamHandlerBuilder heartbeatInterval(Duration heartbeatInterval) {
this.heartbeatInterval = heartbeatInterval;
return this;
}
public ImapChannelUpstreamHandler build() {
- return new ImapChannelUpstreamHandler(hello, processor, encoder, compress, secure, imapMetrics, authenticationConfiguration, (int) heartbeatInterval.toSeconds());
+ return new ImapChannelUpstreamHandler(hello, processor, encoder, compress, secure, imapMetrics, authenticationConfiguration, ignoreIDLEUponProcessing, (int) heartbeatInterval.toSeconds());
}
}
@@ -141,9 +146,11 @@ public class ImapChannelUpstreamHandler extends ChannelInboundHandlerAdapter imp
private final Metric imapCommandsMetric;
+ private final boolean ignoreIDLEUponProcessing;
+
public ImapChannelUpstreamHandler(String hello, ImapProcessor processor, ImapEncoder encoder, boolean compress,
Encryption secure, ImapMetrics imapMetrics, AuthenticationConfiguration authenticationConfiguration,
- int heartbeatIntervalSeconds) {
+ boolean ignoreIDLEUponProcessing, int heartbeatIntervalSeconds) {
this.hello = hello;
this.processor = processor;
this.encoder = encoder;
@@ -152,6 +159,7 @@ public class ImapChannelUpstreamHandler extends ChannelInboundHandlerAdapter imp
this.authenticationConfiguration = authenticationConfiguration;
this.imapConnectionsMetric = imapMetrics.getConnectionsMetric();
this.imapCommandsMetric = imapMetrics.getCommandsMetric();
+ this.ignoreIDLEUponProcessing = ignoreIDLEUponProcessing;
this.heartbeatHandler = new ImapHeartbeatHandler(heartbeatIntervalSeconds, heartbeatIntervalSeconds, heartbeatIntervalSeconds);
}
@@ -252,7 +260,7 @@ public class ImapChannelUpstreamHandler extends ChannelInboundHandlerAdapter imp
})
.doFinally(Throwing.consumer(signal -> super.channelInactive(ctx)))
.subscribe(any -> {
-
+
}, e -> {
LOGGER.error("Exception while handling errors for channel {}", ctx.channel(), e);
Channel channel = ctx.channel();
@@ -270,15 +278,8 @@ public class ImapChannelUpstreamHandler extends ChannelInboundHandlerAdapter imp
ImapSession session = ctx.channel().attr(IMAP_SESSION_ATTRIBUTE_KEY).get();
ImapResponseComposer response = new ImapResponseComposerImpl(new ChannelImapResponseWriter(ctx.channel()));
ImapMessage message = (ImapMessage) msg;
- ChannelPipeline cp = ctx.pipeline();
- try {
- cp.addBefore(NettyConstants.CORE_HANDLER, NettyConstants.HEARTBEAT_HANDLER, heartbeatHandler);
- } catch (IllegalArgumentException e) {
- try (Closeable closeable = mdc(ctx).build()) {
- LOGGER.info("heartbeat handler is already part of this pipeline", e);
- }
- }
+ beforeIDLEUponProcessing(ctx);
ResponseEncoder responseEncoder = new ResponseEncoder(encoder, response);
processor.processReactive(message, responseEncoder, session)
.doOnSuccess(type -> {
@@ -307,13 +308,7 @@ public class ImapChannelUpstreamHandler extends ChannelInboundHandlerAdapter imp
})
.doOnEach(Throwing.consumer(signal -> {
if (signal.isOnComplete() || signal.isOnError()) {
- try {
- ctx.pipeline().remove(NettyConstants.HEARTBEAT_HANDLER);
- } catch (NoSuchElementException e) {
- try (Closeable mdc = ReactorUtils.retrieveMDCBuilder(signal).build()) {
- LOGGER.info("Heartbeat handler was concurrently removed");
- }
- }
+ afterIDLEUponProcessing(ctx);
if (message instanceof Closeable) {
((Closeable) message).close();
}
@@ -325,4 +320,23 @@ public class ImapChannelUpstreamHandler extends ChannelInboundHandlerAdapter imp
.subscribe();
}
+ private void beforeIDLEUponProcessing(ChannelHandlerContext ctx) {
+ if (!ignoreIDLEUponProcessing) {
+ try {
+ ctx.pipeline().addBefore(NettyConstants.CORE_HANDLER, NettyConstants.HEARTBEAT_HANDLER, heartbeatHandler);
+ } catch (IllegalArgumentException e) {
+ LOGGER.info("heartbeat handler is already part of this pipeline", e);
+ }
+ }
+ }
+
+ private void afterIDLEUponProcessing(ChannelHandlerContext ctx) {
+ if (!ignoreIDLEUponProcessing) {
+ try {
+ ctx.pipeline().remove(NettyConstants.HEARTBEAT_HANDLER);
+ } catch (NoSuchElementException e) {
+ LOGGER.info("Heartbeat handler was concurrently removed");
+ }
+ }
+ }
}
diff --git a/server/protocols/protocols-imap4/src/main/resources/imapserver.xml b/server/protocols/protocols-imap4/src/main/resources/imapserver.xml
index 5040827a18..20332056d3 100644
--- a/server/protocols/protocols-imap4/src/main/resources/imapserver.xml
+++ b/server/protocols/protocols-imap4/src/main/resources/imapserver.xml
@@ -52,6 +52,9 @@
<connectionLimitPerIP> 0 </connectionLimitPerIP>
</handler>
+ <!-- Allow disabling the heartbeat handler -->
+ <ignoreIDLEUponProcessing>true</ignoreIDLEUponProcessing>
+
</imapserver>
</imapservers>
diff --git a/src/site/xdoc/server/config-imap4.xml b/src/site/xdoc/server/config-imap4.xml
index 399c9f1a64..77c923d68d 100644
--- a/src/site/xdoc/server/config-imap4.xml
+++ b/src/site/xdoc/server/config-imap4.xml
@@ -97,6 +97,8 @@
<dd>Claim string uses to identify user. E.g: "email_address". Only configure this when you want to authenticate IMAP server using a OIDC provider.</dd>
<dt><strong>auth.oidc.scope</strong></dt>
<dd>An OAuth scope that is valid to access the service (RF: RFC7628). Only configure this when you want to authenticate IMAP server using a OIDC provider.</dd>
+ <dt><strong>ignoreIDLEUponProcessing</strong></dt>
+ <dd>true or false - Allow disabling the heartbeat handler. Defaults to true.</dd>
</dl>
<subsection name="OIDC set up">
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org