Synchronoss should create temp directory lazily

The SynchronossPartHttpMessageReader should only create temp directory
when needed, not at startup.

Closes gh-27092
This commit is contained in:
Arjen Poutsma
2021-06-23 15:59:46 +02:00
parent c5a138a167
commit 7b34bf2a6c

View File

@@ -17,7 +17,6 @@
package org.springframework.http.codec.multipart; package org.springframework.http.codec.multipart;
import java.io.IOException; import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.channels.Channels; import java.nio.channels.Channels;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel; import java.nio.channels.ReadableByteChannel;
@@ -31,6 +30,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.synchronoss.cloud.nio.multipart.DefaultPartBodyStreamStorageFactory; import org.synchronoss.cloud.nio.multipart.DefaultPartBodyStreamStorageFactory;
@@ -46,6 +46,7 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.FluxSink; import reactor.core.publisher.FluxSink;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import reactor.core.publisher.SignalType; import reactor.core.publisher.SignalType;
import reactor.core.scheduler.Schedulers;
import org.springframework.core.ResolvableType; import org.springframework.core.ResolvableType;
import org.springframework.core.codec.DecodingException; import org.springframework.core.codec.DecodingException;
@@ -93,7 +94,7 @@ public class SynchronossPartHttpMessageReader extends LoggingCodecSupport implem
private int maxParts = -1; private int maxParts = -1;
private Path fileStorageDirectory = createTempDirectory(); private final AtomicReference<Path> fileStorageDirectory = new AtomicReference<>();
/** /**
@@ -178,15 +179,16 @@ public class SynchronossPartHttpMessageReader extends LoggingCodecSupport implem
@Override @Override
public Flux<Part> read(ResolvableType elementType, ReactiveHttpInputMessage message, Map<String, Object> hints) { public Flux<Part> read(ResolvableType elementType, ReactiveHttpInputMessage message, Map<String, Object> hints) {
return Flux.create(new SynchronossPartGenerator(message, this.fileStorageDirectory)) return getFileStorageDirectory().flatMapMany(directory ->
.doOnNext(part -> { Flux.create(new SynchronossPartGenerator(message, directory))
if (!Hints.isLoggingSuppressed(hints)) { .doOnNext(part -> {
LogFormatUtils.traceDebug(logger, traceOn -> Hints.getLogPrefix(hints) + "Parsed " + if (!Hints.isLoggingSuppressed(hints)) {
(isEnableLoggingRequestDetails() ? LogFormatUtils.traceDebug(logger, traceOn -> Hints.getLogPrefix(hints) + "Parsed " +
LogFormatUtils.formatValue(part, !traceOn) : (isEnableLoggingRequestDetails() ?
"parts '" + part.name() + "' (content masked)")); LogFormatUtils.formatValue(part, !traceOn) :
} "parts '" + part.name() + "' (content masked)"));
}); }
}));
} }
@Override @Override
@@ -194,13 +196,29 @@ public class SynchronossPartHttpMessageReader extends LoggingCodecSupport implem
return Mono.error(new UnsupportedOperationException("Cannot read multipart request body into single Part")); return Mono.error(new UnsupportedOperationException("Cannot read multipart request body into single Part"));
} }
private static Path createTempDirectory() { private Mono<Path> getFileStorageDirectory() {
try { return Mono.defer(() -> {
return Files.createTempDirectory(FILE_STORAGE_DIRECTORY_PREFIX); Path directory = this.fileStorageDirectory.get();
} if (directory != null) {
catch (IOException ex) { return Mono.just(directory);
throw new UncheckedIOException(ex); }
} else {
return Mono.fromCallable(() -> {
Path tempDirectory = Files.createTempDirectory(FILE_STORAGE_DIRECTORY_PREFIX);
if (this.fileStorageDirectory.compareAndSet(null, tempDirectory)) {
return tempDirectory;
}
else {
try {
Files.delete(tempDirectory);
}
catch (IOException ignored) {
}
return this.fileStorageDirectory.get();
}
}).subscribeOn(Schedulers.boundedElastic());
}
});
} }