I have a table in Postgres holding file uploads. I also have a requirement to download a subset of these files as a zip file to the user.
In order to keep a handle on memory and disk IO, I have managed to stream this content straight from the DB to the client. What I have is code that uses Ecto.stream
to pluck 10 rows at a time from the DB, send the relevant data to Zap (a streaming zipfile builder), which is then chunked out to the client. All very neat and it works.
def send_zip_contents(id, chunker) do
query = << an ecto query returning file metadata and contents >>
one_mb = 1024 * 1024
Repo.transaction fn ->
query
|> Repo.stream(max_rows: 10)
|> Stream.map(fn upload -> {upload.name, upload.contents} end)
|> Zap.into_stream(one_mb)
|> chunker.()
end
end
Unfortunately, I need to add one extra file to that zip archive. A summary file that’s not in the DB. My question is this: Is there a way to add one more Zap Entry tuple, i.e. {somefile.name, somefile.contents}
, into that stream without breaking it? Some way, for instance, of having Stream.map
produce one extra element?