Skip to content

Discussion: Improve consistency of stream interface #32

@timwis

Description

@timwis

At the moment:

  • export is an async method that takes one string param and returns a promise that resolves to a readable stream. Callers can then encode it to csv by piping the returned stream to a writable csv encoder stream.
  • import is an async method that takes several params, including a readable stream, and returns a promise (no resolved value applicable). CSV decoding happens within the method.
  • compare is an async method that takes two string params and returns a promise that resolves to an array of objects
  • merge is an async method that takes a few string params and returns a promise (no resolved value applicable)

The main issue I have is with where csv encoding/decoding happens (it's different in import vs export). I'm thinking it should always happen outside (at the server/cli level) and the methods should just deal with object streams.

But moving csv decoding to the server is a bit tricky because of the way we pass the readable stream to the import method, as an argument. The method then calls a couple async functions, and then attaches the .on('data') and .on('error') handlers.

The trouble is that the flow is activated back in server when we { data: req.body.pipe(csvParser()) }, and the error handler isn't attached until after some async functions, so early errors are missed. Normally a stream interface would look something like

const importStream = await gitSheets.import(opts)
req.body.pipe(csvParser()).pipe(importStream)

So that means the import method should probably take the opts and return a writable stream.

And while we're at it, compare may as well return a readable stream of the diffs since that's what export does. The combination of promises and streams can be a bit confusing, but the alternative of just dealing with promises and not streams makes us less equipped to deal with large CSV files (though maybe it's premature optimisation).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions