Created https://issues.apache.org/jira/browse/MRESOLVER-361 to track the issue.
On Fri, May 19, 2023 at 11:27 PM Finkelman, Jacob <jfink...@amazon.com.invalid> wrote: > During a maven publish if the server closes the TCP connection after the > upload of an asset sometimes the publish will fail with a failed to respond > while attempting to upload the checksum. The correct behavior to wanting to > send more HTTP requests on a closed TCP connection, is to open a new TCP > connection. If the client and server have a low latency connection, say in > the same data center, when the connection is closed a new one appears to > reliably be opened. During higher latency scenarios, in our case when the > client and server are on different continents, maven attempts to reuse the > connection that the server has already closed receiving a failed to respond > error about half the time. On even slower connections we get a Connection > or outbound has closed error. > > Unfortunately, this connection does not get retried. It immediately fails > to build no matter how many retries are configured. I believe this is the > known https://issues.apache.org/jira/browse/MDEPLOY-162 If these requests > were retried on this error, I suspect the entire situation would not have > been a problem. The lack of retries go through different code paths > depending on the transport implementation. > > The wagon transport fails with > org.apache.maven.wagon.providers.http.httpclient.client.NonRepeatableRequestException: > Cannot retry request with a non-repeatable request entity. Fixing the wagon > transport requires changes in maven-wagon and in maven-resolver. In > particular the WagonHttpEntity needs to use a stream supplier in order to > be retryable. My colleague sketched out these changes a year ago. See > https://github.com/mmarston/maven-wagon/commit/4419140ff7794a548f3f9cb9e320fcd20420b5e0 > and > https://github.com/mmarston/maven-resolver/commit/cf00080ac546bda588bd86a44f93c037f7638145 > > The native transport does not have this limitation because when uploading > checksums it uses a PutTaskEntity that is retryable because the PutTask > that it wraps around is essentially a stream supplier. Here< > https://github.com/apache/maven-resolver/blob/89dadad860dc802fd328f2c7a29e7285b599ecde/maven-resolver-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java#L635>. > For the native transport my colleagues think the issue is that it only > supports retry when the client detects the closed connection before or > while sending the request. But if the client sends the request and then > detects the closed connection while trying to read the response, then it > won't retry. In particular the native transport uses > DefaultHttpRequestRetryHandler with requestSentRetryEnabled set to false > (see here< > https://github.com/apache/maven-resolver/blob/d0f8564846863c8a88f2fb1da8391fc860517192/maven-resolver-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java#L239>). > One way to fix the native transport is to change requestSentRetryEnabled to > true when constructing DefaultHttpRequestRetryHandler. Another option is to > use StandardHttpRequestRetryHandler instead because it treats PUT requests > as idempotent so will retry a PUT request even when requestSentRetryEnabled > is false. > > Oddly, if only one checksum algorithm is selected by using > -Daether.checksums.algorithms=MD5 then the entire build fails on this error > but if two or more algorithms are selected > -Daether.checksums.algorithms=MD5,SHA-1 each checksum throws a warning but > the overall build succeeds. It seems odd that the behavior is inconsistent > here. I would expect it either to always throw a warning if a requested > checksum failed upload, or to always fail the build if any checksum failed > upload. The behavior with multiple checksums requested makes it clear that > this failed to respond error can be caught by mvn. > > Using -Daether.connector.http.reuseConnections=false makes this error go > away, because maven never tries sending data over an existing TCP > connection. > > I am new to the maven dev community and was not sure what the best > practice was for reporting these kinds of issues. Starting a conversation > on the mailing list seems like a good place to start. What should happen > next? Which of these issues deserve tickets? What more information should I > provide and where? What PRs would be appreciated to help fix the issues? > > A stack trace from running "mvn deploy" with Apache Maven 3.9.2 > (c9616018c7a021c1c39be70fb2843d6f5f9b8a1c) > > org.apache.http.NoHttpResponseException: ...:443 failed to respond > at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead > (DefaultHttpResponseParser.java:141) > at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead > (DefaultHttpResponseParser.java:56) > at org.apache.http.impl.io.AbstractMessageParser.parse > (AbstractMessageParser.java:259) > at > org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader > (DefaultBHttpClientConnection.java:163) > at org.apache.http.impl.conn.CPoolProxy.receiveResponseHeader > (CPoolProxy.java:157) > at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse > (HttpRequestExecutor.java:273) > at org.apache.http.protocol.HttpRequestExecutor.execute > (HttpRequestExecutor.java:125) > at org.apache.http.impl.execchain.MainClientExec.execute > (MainClientExec.java:272) > at org.apache.http.impl.execchain.ProtocolExec.execute > (ProtocolExec.java:186) > at org.apache.http.impl.execchain.RetryExec.execute (RetryExec.java:89) > at org.apache.http.impl.execchain.RedirectExec.execute > (RedirectExec.java:110) > at org.apache.http.impl.client.InternalHttpClient.doExecute > (InternalHttpClient.java:185) > at org.apache.http.impl.client.CloseableHttpClient.execute > (CloseableHttpClient.java:72) > at org.eclipse.aether.transport.http.HttpTransporter.execute > (HttpTransporter.java:393) > at org.eclipse.aether.transport.http.HttpTransporter.implPut > (HttpTransporter.java:377) > at org.eclipse.aether.spi.connector.transport.AbstractTransporter.put > (AbstractTransporter.java:107) > at > org.eclipse.aether.connector.basic.BasicRepositoryConnector$PutTaskRunner.uploadChecksum > (BasicRepositoryConnector.java:608) > at > org.eclipse.aether.connector.basic.BasicRepositoryConnector$PutTaskRunner.uploadChecksums > (BasicRepositoryConnector.java:591) at > org.eclipse.aether.connector.basic.BasicRepositoryConnector$PutTaskRunner.runTask > (BasicRepositoryConnector.java:565) > at > org.eclipse.aether.connector.basic.BasicRepositoryConnector$TaskRunner.run > (BasicRepositoryConnector.java:414) > at org.eclipse.aether.connector.basic.BasicRepositoryConnector.put > (BasicRepositoryConnector.java:319) > at org.eclipse.aether.internal.impl.DefaultDeployer.deploy > (DefaultDeployer.java:298) > at org.eclipse.aether.internal.impl.DefaultDeployer.deploy > (DefaultDeployer.java:201) > at org.eclipse.aether.internal.impl.DefaultRepositorySystem.deploy > (DefaultRepositorySystem.java:392) > at org.apache.maven.plugins.deploy.AbstractDeployMojo.deploy > (AbstractDeployMojo.java:139) > at org.apache.maven.plugins.deploy.DeployMojo.execute > (DeployMojo.java:191) > at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo > (DefaultBuildPluginManager.java:126) > at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 > (MojoExecutor.java:342) > at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute > (MojoExecutor.java:330) > at org.apache.maven.lifecycle.internal.MojoExecutor.execute > (MojoExecutor.java:213) > at org.apache.maven.lifecycle.internal.MojoExecutor.execute > (MojoExecutor.java:175) > at org.apache.maven.lifecycle.internal.MojoExecutor.access$000 > (MojoExecutor.java:76) > at org.apache.maven.lifecycle.internal.MojoExecutor$1.run > (MojoExecutor.java:163) > at org.apache.maven.plugin.DefaultMojosExecutionStrategy.execute > (DefaultMojosExecutionStrategy.java:39) > at org.apache.maven.lifecycle.internal.MojoExecutor.execute > (MojoExecutor.java:160) > at > org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject > (LifecycleModuleBuilder.java:105) > at > org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject > (LifecycleModuleBuilder.java:73) > at > org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build > (SingleThreadedBuilder.java:53) > at org.apache.maven.lifecycle.internal.LifecycleStarter.execute > (LifecycleStarter.java:118) > at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:261) > at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:173) > at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:101) > at org.apache.maven.cli.MavenCli.execute (MavenCli.java:910) > at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:283) > at org.apache.maven.cli.MavenCli.main (MavenCli.java:206) > at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native > Method) > at jdk.internal.reflect.NativeMethodAccessorImpl.invoke > (NativeMethodAccessorImpl.java:62) > at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke > (DelegatingMethodAccessorImpl.java:43) > at java.lang.reflect.Method.invoke (Method.java:566) > at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced > (Launcher.java:283) > at org.codehaus.plexus.classworlds.launcher.Launcher.launch > (Launcher.java:226) > at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode > (Launcher.java:407) > at org.codehaus.plexus.classworlds.launcher.Launcher.main > (Launcher.java:348) > >