-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conform to a Stream Interface #832
Comments
Oh and I'd love to have a test suite that proves we confirm. How do we test streams? |
A bit of an info dump follows — apologies if this repeats stuff you already know! Here's the streams3 flow from the perspective of the events emitted (relations are temporal, not indicative of causation): And a (slightly out of date, but not horribly so) interaction chart of methods for streams3 (relations are causative, not temporal!): A couple of differences jump out at me when comparing and contrasting the stream implementation in serialport vs. the charts above (& implementation code): 1️⃣ 2️⃣ Is probably the trickier difference: The idea is that streams2+ readable streams are backed by a lower level resource — in this case, our Luckily, it appears that the existing implementation is only missing the 3️⃣ There will be some differences in 4️⃣ Apologies again for the info dump — hopefully this helps! I'm happy to answer any questions that arise from this as well! |
This is beautiful @chrisdickinson this is exactly what I needed. Do you know which node version streams 2 appeared in? We have a very wide range of support. |
Streams2 first appeared (in early form) in |
In order to conform with Streams3, serial-port should inherits from Duplex from readable-stream. It's basically a rewrite, in the sense that most of the code in https://github.com/EmergingTechnologyAdvisors/node-serialport/blob/master/lib/serialport.js#L328-L347 is to deal with streams. All of that should be handled by Duplex, and the only bits should be dealing Currently we are targeting node v0.10 with readable-stream, so it will not be ok to use on v0.8 (not sure if you still support 0.8 or not). |
We only go back to 10, so that's OK. Having less code off our own is OK too. What's the best way to test? On Mon, May 30, 2016, 6:26 AM Matteo Collina [email protected]
|
just pipe an instance of |
Hi @chrisdickinson and @mcollina I did a spike on implementing streams today and have a few questions.
We have an open/not open states (Including opening, closing and closed as not open states.) How do we communicate that with stream semantics? Currently we throw errors and make people wait for our I checked out What do you think? Thanks! |
I will fill up the internal buffer, and in turn the heap of your node process. It's basically an externally-driven memory leak. However, buffering unlimited amount of data makes very little sense from a program point of view, so you can probably code some bits to mitigate. I highly recommend controlling the buffering window from Node.
Why not? Can you please articulate?
The stream interface has a very specific state machine. node-serialport was born before that state machine was finalized. Can you please articulate on what those states mean? |
I'd like to make some flow charts to help show how SP currently works, what did you use to make yours? I was looking at We have a port object that starts closed, we have async
|
as far as I remember, serialport is polling for reads at c++ level, right? I think the best starting point would be to avoid that in the first place. |
only on windows, which is why I brought it up |
I'm continuing to work on this in #906 and have come to what feels like the most complex interface I've moved our c++ code into an abstraction (currently being called the I'm stuck on what I want reading to look like. Should we ask the I know var binding = new Binding({ push: push, disconnect: disconnectCB});
binding.startReading(bytes);
describe('#startReading', function() {
it('keeps calling push() until it returns false');
it("doesn't mind being called multiple times");
it('always calls push at least once');
}); This would allow the A more simple api might be. var binding = new Binding({ disconnect: disconnectCB});
binding.read(function(data) {
// data is a buffer that is guaranteed to have at least 1 byte of data
// binding is required to call the disconnect callback if the port is unexpectedly closed
});
describe('#read', function() {
it('returns with available data when it becomes available');
}); In the back in my head I think this limits bindings and might possibly cause data bottlenecks down the line but I haven't gamed it out. I'd love some feedback. |
I think you either have two options, a push interface or a pull interface. Both approach are sound. push interfacefunction push (data) {
console.log(data)
}
// emits 'error' if something goes wrong
var binding = new Binding({ push });
binding.start()
setInterval(function () {
if (binding.running) {
binding.pause()
} else {
binding.resume()
}
}, 1000)
setTimeout(function () {
binding.stop()
}, 10000) This is essentially the same that you have right now, maybe in a different form. The serial port pushes data to the JS world. With this API, the actual high-level work would be to offer this through a pull interfacevar binding = new Binding();
binding.read(function(err, data) {
// data is a buffer that is guaranteed to have at least 1 byte of data
// err is present if the port is unexpectedly closed
}); This is extremely simpler from serial-port perspective, but it put more work on the binding developers. I think that's a good thing, because it also keep a very simple API interface for bindings. Some bindings might end up implementing some form of buffering themselves, if they cannot |
I'd even argue the pull interface maps to Though I do notice that chrome serialport and the web serialport spec on the other hand are push interfaces, so they'd have to jump through some hoops, but at least that would all be in JS land. |
I've merged #906, and I'm wondering if we're doing |
🔥🔥🔥 |
We currently emit data events, and are sort of pausable (not sure if we're implemented correctly) but don't conform to a streams interface. Since we're compatible across node 0.10 through 6 we need to make sure we stay compatible if possible. If not, what is different?
The text was updated successfully, but these errors were encountered: