У меня есть Postgres BlobInputStream
, который связан с транзакцией базы данных, и мне нужно передать его клиенту, который запрашивает его через HTTP-запрос.
Чтобы избежать медленных клиентов из-за потери транзакций базы данных,Я хочу сбросить поток на диск и одновременно позволить клиенту читать с диска: таким образом, транзакция завершится, когда поток будет записан на диск, даже если клиент все еще читает из файла.
Очевидно, я не хочу, чтобы клиент ожидал сброса всего потока на диск перед началом чтения.
На данный момент это мой код:
public void transferStreamToChannel(InputStream stream, SinkChannel channel) {
try {
// Create a temporary file to buffer to stream transfer, so that slow readers won't
// starve the transaction.
var tmp = Files.createTempFile(StreamTransferInitiator.class.getSimpleName(),
Thread.currentThread().getName());
var tos = Files.newOutputStream(tmp);
var executor = Executors.newSingleThreadExecutor();
executor.execute(() -> {
try (var fis = Files.newInputStream(tmp, StandardOpenOption.DELETE_ON_CLOSE)) {
var out = Channels.newOutputStream(channel);
fis.transferTo(out);
} catch (IOException e) {
this.getLogger().error("Error writing to disk", e);
}
});
stream.transferTo(tos);
} catch (IOException e) {
this.getLogger().error("Error reading stream", e);
} finally {
try {
stream.close();
channel.close();
} catch (IOException e) {
this.getLogger().error("Error closing stream", e);
}
}
}
Проблема с этимчто исполнитель найдет пустой файл и закроется до того, как поток базы данных будет полностью очищен.
Как мне соединить две операции, чтобы при передаче клиенту было известно о большем количестве данных, которые еще предстоит записатьна диск?