forked from lix-project/lix
libstore: split callback
into metadata and finished parts
this will let us return metadata from FileTransfer::download, which in
turn is necessary to remove enqueueDownload. it also opens avenues for
streaming downloads that keep download metadata instead of dropping it
Change-Id: If0fc6af5eb2aeb689fc866c345c9d7bce4d59f2d
This commit is contained in:
parent
923abe347c
commit
14eff10fe4
|
@ -60,7 +60,8 @@ struct curlFileTransfer : public FileTransfer
|
|||
/// transfer complete, result or failure reported
|
||||
transferComplete,
|
||||
} phase = initialSetup;
|
||||
std::packaged_task<FileTransferResult(std::exception_ptr, FileTransferResult)> callback;
|
||||
std::promise<FileTransferResult> metadataPromise;
|
||||
std::packaged_task<void(std::exception_ptr)> doneCallback;
|
||||
std::function<void(std::string_view data)> dataCallback;
|
||||
CURL * req; // must never be nullptr
|
||||
std::string statusMsg;
|
||||
|
@ -100,7 +101,7 @@ struct curlFileTransfer : public FileTransfer
|
|||
const std::string & uri,
|
||||
const Headers & headers,
|
||||
ActivityId parentAct,
|
||||
std::invocable<std::exception_ptr> auto callback,
|
||||
std::invocable<std::exception_ptr> auto doneCallback,
|
||||
std::function<void(std::string_view data)> dataCallback,
|
||||
std::optional<std::string> uploadData,
|
||||
bool noBody
|
||||
|
@ -112,9 +113,8 @@ struct curlFileTransfer : public FileTransfer
|
|||
{uri}, parentAct)
|
||||
, uploadData(std::move(uploadData))
|
||||
, noBody(noBody)
|
||||
, callback([cb{std::move(callback)}] (std::exception_ptr ex, FileTransferResult r) {
|
||||
, doneCallback([cb{std::move(doneCallback)}] (std::exception_ptr ex) {
|
||||
cb(ex);
|
||||
return r;
|
||||
})
|
||||
, dataCallback(std::move(dataCallback))
|
||||
, req(curl_easy_init())
|
||||
|
@ -143,8 +143,11 @@ struct curlFileTransfer : public FileTransfer
|
|||
void failEx(std::exception_ptr ex)
|
||||
{
|
||||
assert(phase != transferComplete);
|
||||
if (phase == initialSetup) {
|
||||
metadataPromise.set_exception(ex);
|
||||
}
|
||||
phase = transferComplete;
|
||||
callback(ex, std::move(result));
|
||||
doneCallback(ex);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
|
@ -178,6 +181,9 @@ struct curlFileTransfer : public FileTransfer
|
|||
|
||||
result.cached = getHTTPStatus() == 304;
|
||||
|
||||
if (phase == initialSetup) {
|
||||
metadataPromise.set_value(result);
|
||||
}
|
||||
phase = transferring;
|
||||
}
|
||||
|
||||
|
@ -399,7 +405,7 @@ struct curlFileTransfer : public FileTransfer
|
|||
{
|
||||
act.progress(bodySize, bodySize);
|
||||
phase = transferComplete;
|
||||
callback(nullptr, std::move(result));
|
||||
doneCallback(nullptr);
|
||||
}
|
||||
|
||||
else {
|
||||
|
@ -718,7 +724,7 @@ struct curlFileTransfer : public FileTransfer
|
|||
|
||||
auto _state = std::make_shared<Sync<State>>();
|
||||
|
||||
auto transfer = enqueueFileTransfer(
|
||||
auto [meta, done] = enqueueFileTransfer(
|
||||
uri,
|
||||
headers,
|
||||
[](std::exception_ptr ex) {
|
||||
|
@ -733,17 +739,21 @@ struct curlFileTransfer : public FileTransfer
|
|||
noBody
|
||||
);
|
||||
|
||||
return std::async(std::launch::deferred, [_state, transfer{std::move(transfer)}]() mutable {
|
||||
auto result = transfer.get();
|
||||
return std::async(
|
||||
std::launch::deferred,
|
||||
[_state, _meta{std::move(meta)}, done{std::move(done)}]() mutable {
|
||||
auto meta = _meta.get();
|
||||
done.get();
|
||||
auto state(_state->lock());
|
||||
return std::pair(std::move(result), std::move(state->data));
|
||||
});
|
||||
return std::pair(std::move(meta), std::move(state->data));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
std::future<FileTransferResult> enqueueFileTransfer(
|
||||
std::pair<std::future<FileTransferResult>, std::future<void>> enqueueFileTransfer(
|
||||
const std::string & uri,
|
||||
const Headers & headers,
|
||||
std::invocable<std::exception_ptr> auto callback,
|
||||
std::invocable<std::exception_ptr> auto doneCallback,
|
||||
std::function<void(std::string_view data)> dataCallback,
|
||||
std::optional<std::string> data,
|
||||
bool noBody
|
||||
|
@ -752,7 +762,8 @@ struct curlFileTransfer : public FileTransfer
|
|||
/* Ugly hack to support s3:// URIs. */
|
||||
if (uri.starts_with("s3://")) {
|
||||
// FIXME: do this on a worker thread
|
||||
return std::async(
|
||||
return {
|
||||
std::async(
|
||||
std::launch::deferred,
|
||||
[uri, dataCallback] {
|
||||
#if ENABLE_S3
|
||||
|
@ -778,20 +789,22 @@ struct curlFileTransfer : public FileTransfer
|
|||
);
|
||||
#endif
|
||||
}
|
||||
);
|
||||
),
|
||||
std::async(std::launch::deferred, []{}),
|
||||
};
|
||||
}
|
||||
|
||||
return enqueueItem(std::make_shared<TransferItem>(
|
||||
auto item = enqueueItem(std::make_shared<TransferItem>(
|
||||
*this,
|
||||
uri,
|
||||
headers,
|
||||
getCurActivity(),
|
||||
std::move(callback),
|
||||
std::move(doneCallback),
|
||||
std::move(dataCallback),
|
||||
std::move(data),
|
||||
noBody
|
||||
))
|
||||
->callback.get_future();
|
||||
));
|
||||
return {item->metadataPromise.get_future(), item->doneCallback.get_future()};
|
||||
}
|
||||
|
||||
bool exists(const std::string & uri, const Headers & headers) override
|
||||
|
@ -819,7 +832,7 @@ struct curlFileTransfer : public FileTransfer
|
|||
|
||||
auto _state = std::make_shared<Sync<State>>();
|
||||
|
||||
enqueueFileTransfer(
|
||||
auto transfer = enqueueFileTransfer(
|
||||
uri,
|
||||
headers,
|
||||
[_state](std::exception_ptr ex) {
|
||||
|
|
Loading…
Reference in a new issue