git ssb

2+

Dominic / pull-stream



Commit 95a94c9b435a241fe1d1f7397572fb7adc45a074

spec

Dominic Tarr committed on 11/27/2015, 4:17:59 AM
Parent: bc44995d8d512c4f68cdf25695b038d794df65c8

Files changed

pull-streams.mddeleted
spec.mdadded
pull-streams.mdView
@@ -1,61 +1,0 @@
1-# Synopsis
2-
3-In Pull-Streams, there are two fundamental types of streams `Source`s and `Sink`s. There are two composite types of streams `Through` (aka transform) and `Duplex`. A Through Stream is a sink stream that reads what goes into the Source Stream, it can also be written to. A duplex stream is a pair of streams (`{Source, Sink}`) streams.
4-
5-# Pull-Streams
6-## Source Streams
7-
8-A Source Stream (aka readable stream) is a async function that may be called repeatedly until it returns a terminal state. Pull-streams have back pressure, but it implicit instead of sending an explicit back pressure signal. If a source
9-needs the sink to slow down, it may delay returning a read. If a sink needs the source to slow down, it just waits until it reads the source again.
10-
11-### Read
12-
13-A method, for example `read(null, cb(end|err))`, will read data from the stream zero or more times. The read method *must not* be called until the previous call has returned, except for a call to abort the stream.
14-
15-### End
16-The stream may be terminated, for example `cb(err|end)`. The read method *must not* be called after it has terminated. As a normal stream end is propagated up the pipeline, an error should be propagated also, because it also means the end of the stream. If `cb(end=true)` that is a "end" which means it's a valid termination, if `cb(err)` that is an error.
17-`error` and `end` are mostly the same. If you are buffering inputs and see an `end`, process those inputs and then the end.
18-If you are buffering inputs and get an `error`, then you _may_ throw away that buffer and return the end.
19-
20-### Abort
21-Sometimes it's the sink that errors, and if it can't read anymore then we _must_ abort the source. (example, source is a file stream from local fs, and sink is a http upload. prehaps the network drops or remote server crashes, in this case we should abort the source, so that it's resources can be released.)
22-
23-To abort the sink, call read with a truthy first argument. You may abort a source _before_ it has returned from a regular read. (if you wait for the previous read to complete, it's possible you'd get a deadlock, if you a reading a stream that takes a long time, example, `tail -f` is reading a file, but nothing has appended to that file yet).
24-
25-## Sink Streams
26-
27-A Sink Stream (aka writable stream) is a function that a Source Stream is passed to. The Sink Stream calls the `read` function of the Source Stream, abiding by the rules about when it may not call.
28-
29-### Abort
30-The Sink Stream may also abort the source if it can no longer read from it.
31-
32-## Through Streams
33-
34-A through stream is a sink stream that returns another source when it is passed a source.
35-A through stream may be thought of as wrapping a source.
36-
37-## Duplex Streams
38-
39-A pair of independent streams, one Source and one Sink. The purpose of a duplex stream is not transformation of the data that passes though it. It's meant for communication only.
40-
41-# Composing Streams
42-
43-Since a Sink is a function that takes a Source, a Source may be fed into a Sink by simply passing the Source to the Sink.
44-For example, `sink(source)`. Since a transform is a Sink that returns a Source, you can just add to that pattern by wrapping the source. For example, `sink(transform(source))`. This works, but it reads from right-to-left, and we are used to left-to-right.
45-
46-A method for creating a left-to-rihght reading pipeline of pull-streams. For example, a method could implement the following interface...
47-
48-```
49-pull([source] [,transform ...] [,sink ...])
50-```
51-
52-The interface could alllow for the following scenarios...
53-
54-1. Connect a complete pipeline: `pull(source, transform,* sink)` this connects a source to a sink via zero or more transforms.
55-
56-2. If a sink is not provided: `pull(source, transform+)` then pull should return the last `source`,
57-this way streams can be easily combined in a functional way.
58-
59-3. If a source is not provided: `pull(transform,* sink)` then pull should return a sink that will complete the pipeline when
60-it's passed a source. `function (source) { return pull(source, pipeline) }`
61-If neither a source or a sink are provided, this will return a source that will return another source (via 2) i.e. a through stream.
spec.mdView
@@ -1,0 +1,61 @@
1+# Synopsis
2+
3+In Pull-Streams, there are two fundamental types of streams `Source`s and `Sink`s. There are two composite types of streams `Through` (aka transform) and `Duplex`. A Through Stream is a sink stream that reads what goes into the Source Stream, it can also be written to. A duplex stream is a pair of streams (`{Source, Sink}`) streams.
4+
5+# Pull-Streams
6+## Source Streams
7+
8+A Source Stream (aka readable stream) is a async function that may be called repeatedly until it returns a terminal state. Pull-streams have back pressure, but it implicit instead of sending an explicit back pressure signal. If a source
9+needs the sink to slow down, it may delay returning a read. If a sink needs the source to slow down, it just waits until it reads the source again.
10+
11+### Read
12+
13+A method, for example `read(null, cb(end|err))`, will read data from the stream zero or more times. The read method *must not* be called until the previous call has returned, except for a call to abort the stream.
14+
15+### End
16+The stream may be terminated, for example `cb(err|end)`. The read method *must not* be called after it has terminated. As a normal stream end is propagated up the pipeline, an error should be propagated also, because it also means the end of the stream. If `cb(end=true)` that is a "end" which means it's a valid termination, if `cb(err)` that is an error.
17+`error` and `end` are mostly the same. If you are buffering inputs and see an `end`, process those inputs and then the end.
18+If you are buffering inputs and get an `error`, then you _may_ throw away that buffer and return the end.
19+
20+### Abort
21+Sometimes it's the sink that errors, and if it can't read anymore then we _must_ abort the source. (example, source is a file stream from local fs, and sink is a http upload. prehaps the network drops or remote server crashes, in this case we should abort the source, so that it's resources can be released.)
22+
23+To abort the sink, call read with a truthy first argument. You may abort a source _before_ it has returned from a regular read. (if you wait for the previous read to complete, it's possible you'd get a deadlock, if you a reading a stream that takes a long time, example, `tail -f` is reading a file, but nothing has appended to that file yet).
24+
25+## Sink Streams
26+
27+A Sink Stream (aka writable stream) is a function that a Source Stream is passed to. The Sink Stream calls the `read` function of the Source Stream, abiding by the rules about when it may not call.
28+
29+### Abort
30+The Sink Stream may also abort the source if it can no longer read from it.
31+
32+## Through Streams
33+
34+A through stream is a sink stream that returns another source when it is passed a source.
35+A through stream may be thought of as wrapping a source.
36+
37+## Duplex Streams
38+
39+A pair of independent streams, one Source and one Sink. The purpose of a duplex stream is not transformation of the data that passes though it. It's meant for communication only.
40+
41+# Composing Streams
42+
43+Since a Sink is a function that takes a Source, a Source may be fed into a Sink by simply passing the Source to the Sink.
44+For example, `sink(source)`. Since a transform is a Sink that returns a Source, you can just add to that pattern by wrapping the source. For example, `sink(transform(source))`. This works, but it reads from right-to-left, and we are used to left-to-right.
45+
46+A method for creating a left-to-rihght reading pipeline of pull-streams. For example, a method could implement the following interface...
47+
48+```
49+pull([source] [,transform ...] [,sink ...])
50+```
51+
52+The interface could alllow for the following scenarios...
53+
54+1. Connect a complete pipeline: `pull(source, transform,* sink)` this connects a source to a sink via zero or more transforms.
55+
56+2. If a sink is not provided: `pull(source, transform+)` then pull should return the last `source`,
57+this way streams can be easily combined in a functional way.
58+
59+3. If a source is not provided: `pull(transform,* sink)` then pull should return a sink that will complete the pipeline when
60+it's passed a source. `function (source) { return pull(source, pipeline) }`
61+If neither a source or a sink are provided, this will return a source that will return another source (via 2) i.e. a through stream.

Built with git-ssb-web