Add support for streaming NAR output (#1)

Before this change the NAR contents would be buffered in memory before
supplying them to the client.  Now each chunk is instantly flushed
to the client when it's available.

This requires reworking things so that we use a `StreamingBody`,
which in turn requires passing a Haskell callback to the C code to
invoke.
This commit is contained in:
Gabriella Gonzalez
2022-08-23 16:32:34 -07:00
committed by GitHub
parent 319e70637e
commit 0242d8bebb
3 changed files with 86 additions and 33 deletions

View File

@@ -159,20 +159,40 @@ void signString
copyString(signature, output);
}
void dumpPath(char const * const hashPart, struct string * const output) {
bool dumpPath
( char const * const hashPart
, bool (* const callback)(struct string const * const)
)
{
ref<Store> store = getStore();
std::optional<StorePath> storePath =
store->queryPathFromHashPart(hashPart);
if (storePath.has_value()) {
StringSink sink;
LambdaSink sink([=](std::string_view v) {
struct string s = { .data = v.data(), .size = v.size() };
store->narFromPath(storePath.value(), sink);
bool succeeded = (*callback)(&s);
copyString(sink.s, output);
if (!succeeded) {
// We don't really care about the error message. The only
// reason for throwing an exception here is that this is the
// only way that a Nix sink can exit early.
throw std::runtime_error("");
}
});
try {
store->narFromPath(storePath.value(), sink);
} catch (const std::runtime_error & e) {
// Intentionally do nothing. We're only using the exception as a
// short-circuiting mechanism.
}
return true;
} else {
*output = emptyString;
return false;
}
}