From 923abe347cf391058999f76a9fc957170ba3332f Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Mon, 28 Oct 2024 18:59:43 +0100 Subject: [PATCH] libstore: use data callback for simple downloads too this is an intermediate step towards removing enqueueDownload entirely. Change-Id: I05ec0c7f4a234fdc966e5005308b37f6f905d433 --- src/libstore/filetransfer.cc | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index 018337a8f..3f58d147e 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -60,9 +60,7 @@ struct curlFileTransfer : public FileTransfer /// transfer complete, result or failure reported transferComplete, } phase = initialSetup; - std::packaged_task< - std::pair(std::exception_ptr, FileTransferResult)> - callback; + std::packaged_task callback; std::function dataCallback; CURL * req; // must never be nullptr std::string statusMsg; @@ -114,9 +112,9 @@ struct curlFileTransfer : public FileTransfer {uri}, parentAct) , uploadData(std::move(uploadData)) , noBody(noBody) - , callback([this, cb{std::move(callback)}] (std::exception_ptr ex, FileTransferResult r) { + , callback([cb{std::move(callback)}] (std::exception_ptr ex, FileTransferResult r) { cb(ex); - return std::pair{std::move(r), std::move(downloadData)}; + return r; }) , dataCallback(std::move(dataCallback)) , req(curl_easy_init()) @@ -714,7 +712,13 @@ struct curlFileTransfer : public FileTransfer bool noBody ) { - return enqueueFileTransfer( + struct State { + std::string data; + }; + + auto _state = std::make_shared>(); + + auto transfer = enqueueFileTransfer( uri, headers, [](std::exception_ptr ex) { @@ -722,13 +726,21 @@ struct curlFileTransfer : public FileTransfer std::rethrow_exception(ex); } }, - {}, + [_state](std::string_view data) { + _state->lock()->data.append(data); + }, std::move(data), noBody ); + + return std::async(std::launch::deferred, [_state, transfer{std::move(transfer)}]() mutable { + auto result = transfer.get(); + auto state(_state->lock()); + return std::pair(std::move(result), std::move(state->data)); + }); } - std::future> enqueueFileTransfer( + std::future enqueueFileTransfer( const std::string & uri, const Headers & headers, std::invocable auto callback, @@ -742,7 +754,7 @@ struct curlFileTransfer : public FileTransfer // FIXME: do this on a worker thread return std::async( std::launch::deferred, - [uri]() -> std::pair { + [uri, dataCallback] { #if ENABLE_S3 auto [bucketName, key, params] = parseS3Uri(uri); @@ -758,7 +770,8 @@ struct curlFileTransfer : public FileTransfer FileTransferResult res; if (!s3Res.data) throw FileTransferError(NotFound, "S3 object '%s' does not exist", uri); - return {res, std::move(*s3Res.data)}; + dataCallback(*s3Res.data); + return res; #else throw nix::Error( "cannot download '%s' because Lix is not built with S3 support", uri