You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When TransferManager multipart upload has part transfer failures, TRANSFER_FAILED_EVENT is sent back to the clients on the first failure. However, if later parts are successful then additional events are send back to the client. This might be alright, because at least "TRANSFER_FAILED_EVENT" was notified to the client. However I suspect here that TRANSFER_FAILED_EVENT should be a terminal event and upon this event, a client might be taking actions to correct the failure, which could be interfered with by outstanding transfers.
Steps:
(1) Start N multipart xfers.
(2) iptables DROP the connection (see code below)
(3) TRANSFER_FAILED_EVENT is received by the client
Expected: TRANSFER_FAILED_EVENT indicates the transfer is completed, and in a terminal state. No further events are expected to be received.
Actual: Further successful events are received by listeners well after the failure event.
This might be expected behavior, but it's unclear due to TRANSFER_FAILED_EVENT not being documented.
`
val uploads = mutableMapOf<String, Upload>()
val uploadLastCallbackEvents = ConcurrentHashMap<String, ProgressEventType>()
val isNetworkBlockerStarted = AtomicBoolean(false)
val fileKeys = mutableListOf(
"file42mb",
"file22mb",
"file18mb",
"file10mb"
)
fun main() {
netUp()
val accessKey = "zzzz"
val secretKey = "xyz"
val s3Client = AmazonS3ClientBuilder.standard().withRegion("us-east-1").withCredentials(object :AWSCredentialsProvider{
override fun getCredentials(): AWSCredentials {
return BasicAWSCredentials(accessKey, secretKey)
}
override fun refresh() {
}
}).build()
ClientConfiguration().withRetryMode(RetryMode.STANDARD).withRetryPolicy(PredefinedRetryPolicies.getDefaultRetryPolicyWithCustomMaxRetries(20))
val transferManager = TransferManagerBuilder.standard()
.withS3Client(s3Client)
.withExecutorFactory { Executors.newFixedThreadPool(3) }
.build()
println("start")
fileKeys.forEach{ file ->
val upload = transferManager.upload(
new PutObjectRequest("fried-chicken",
File(file).name,
File(file)
))
upload[file] = upload
upload.addProgressListener(ProgressListener {
blockNetwork()
uploadLastCallbackEvents[file] = it.eventType
println("Progress event $it --> $file")
})
}
while (true){
println("\n---------------------------------------------------------------------------")
uploads.forEach{ (key, upload) ->
blockNetwork()
println(" State is : ${upload.state} ==> $key ==> ${uploadLastCallbackEvents[key]}")
}
println("---------------------------------------------------------------------------\n")
TimeUnit.SECONDS.sleep(5)
}
}
fun blockNetwork() {
if (!isNetworkBlockerStarted.getAndSet(true)) {
thread(start = true) {
// give some time for transfers to start
TimeUnit.SECONDS.sleep(1)
for (i in 1..5){
netDown(i)
if (i == 5){
println("\n\n\nLAST TIME!\n\n\n")
TimeUnit.SECONDS.sleep(6)
} else {
TimeUnit.SECONDS.sleep(40)
}
The text was updated successfully, but these errors were encountered:
jamesceddy
changed the title
TransferManager Parrellel uploads send TRANSFER_FAILURE but continue transfering after the failure.
TransferManager parallel uploads send TRANSFER_FAILURE but continue transfering after the failure.
Mar 16, 2020
jamesceddy
added a commit
to jamesceddy/aws-sdk-java
that referenced
this issue
Mar 17, 2020
Suppose we have 10 parts, if we fail on part aws#2 we fire a "TRANFER_FAILED_EVENT" back to the client. We should assume that
clients will react to this failure, possibly with custom logic to retry. Supposing that part aws#3 succeeds, the client will then get
other transfer events past the "TRANSFER_FAILED_EVENT". I assume here that "TRANSFER_FAILED_EVENT" is a terminal event and that
a client should not expect to receive further events for that transfer, successful or not. However, the meaning of TRANSFER_FAILED_EVENT
is not clearly defined in the javadocs.
fixes: aws#2267
zoewangg
added
bug
This issue is a bug.
and removed
investigating
This issue is being investigated and/or work is in progress to resolve the issue.
labels
Mar 20, 2020
When TransferManager multipart upload has part transfer failures, TRANSFER_FAILED_EVENT is sent back to the clients on the first failure. However, if later parts are successful then additional events are send back to the client. This might be alright, because at least "TRANSFER_FAILED_EVENT" was notified to the client. However I suspect here that TRANSFER_FAILED_EVENT should be a terminal event and upon this event, a client might be taking actions to correct the failure, which could be interfered with by outstanding transfers.
Steps:
(1) Start N multipart xfers.
(2) iptables DROP the connection (see code below)
(3) TRANSFER_FAILED_EVENT is received by the client
Expected: TRANSFER_FAILED_EVENT indicates the transfer is completed, and in a terminal state. No further events are expected to be received.
Actual: Further successful events are received by listeners well after the failure event.
This might be expected behavior, but it's unclear due to TRANSFER_FAILED_EVENT not being documented.
`
val uploads = mutableMapOf<String, Upload>()
val uploadLastCallbackEvents = ConcurrentHashMap<String, ProgressEventType>()
val isNetworkBlockerStarted = AtomicBoolean(false)
val fileKeys = mutableListOf(
"file42mb",
"file22mb",
"file18mb",
"file10mb"
)
fun main() {
netUp()
val accessKey = "zzzz"
val secretKey = "xyz"
}
fun blockNetwork() {
if (!isNetworkBlockerStarted.getAndSet(true)) {
thread(start = true) {
// give some time for transfers to start
TimeUnit.SECONDS.sleep(1)
for (i in 1..5){
netDown(i)
if (i == 5){
println("\n\n\nLAST TIME!\n\n\n")
TimeUnit.SECONDS.sleep(6)
} else {
TimeUnit.SECONDS.sleep(40)
}
}
fun netUp() {
println("\n\n\nNETWORK UP!\n\n\n")
"/usr/bin/sudo -S /sbin/iptables -D OUTPUT -p tcp --dport 443 -j DROP".runCommand()
}
fun netDown(i:Int){
println("\n\n\nNETWORK DOWN! $i\n\n\n")
"/usr/bin/sudo -S /sbin/iptables -A OUTPUT -p tcp --dport 443 -j DROP".runCommand()
}
fun String.runCommand() {
ProcessBuilder("/bin/bash", "-c", "echo password| $this")
.redirectErrorStream(true)
.redirectOutput(ProcessBuilder.Redirect.INHERIT)
.redirectError(ProcessBuilder.Redirect.INHERIT)
.redirectInput(ProcessBuilder.Redirect.INHERIT)
.start().waitFor()
}
`
The text was updated successfully, but these errors were encountered: