-
Notifications
You must be signed in to change notification settings - Fork 6
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
Client uses ReadStream and WriteStream #136
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm! just nitpicks or observations
router/client.ts
Outdated
span.setStatus({ code: SpanStatusCode.OK }); | ||
}, | ||
); | ||
const readStreamRequestCloseNotImplemented = () => void 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
next(): Promise< | ||
| { | ||
done: false; | ||
value: T; | ||
} | ||
| { | ||
done: true; | ||
value: undefined; | ||
} | ||
>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe this should be its own type lol, seems kind of useful
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had it be part of the interfaces in streams.ts
, but then just inlined it, we'll see if it comes up again.
@@ -364,10 +368,11 @@ describe.each(testMatrix())( | |||
}); | |||
|
|||
// start a stream | |||
const [input, output] = await client.test.echo.stream(); | |||
input.push({ msg: '1', ignore: false }); | |||
const [inputWriter, outputReader] = await client.test.echo.stream(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like you naming these inputWriter
and outputReader
(and on the server, inputReader
and outputWriter
), not too verbose but feels intuitive
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🫡
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to update type annotations to have those names, but maybe we can do that in a follow up since we reference 'input'
and 'output'
in a bunch of places
export function getIteratorFromStream<T>(readStream: ReadStream<T>) { | ||
return readStream[Symbol.asyncIterator](); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still kind of surprised there isn't something like Iterator.from(foo)
in JS
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems like we should be able to just use the stream as an async iterator https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator without this helper?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the for-await-of function automatically calls this, if you want to call next
directly, you have to grab the iterator like this
* Client uses ReadStream * Client uses WriteStream * delete port config lol * Disable everything for handler.test.ts * no void 0
const result = await output.next(); | ||
assert(result.value.ok); | ||
inputWriter.write({ msg: nanoid(), ignore: false }); | ||
const result = await outputReader[Symbol.asyncIterator]().next(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does a bare await outputReader().next();
not work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, you need to grab the iterator
|
||
const result1 = await iterNext(output); | ||
const outputIterator = getIteratorFromStream(outputReader); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also when to use outputReader[Symbol.asyncIterator]
vs getIteratorFromStream(outputReader)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's just a helper, we can either remove getIteratorFromStream
or i'll make sure we're using it everywhere.
export function getIteratorFromStream<T>(readStream: ReadStream<T>) { | ||
return readStream[Symbol.asyncIterator](); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems like we should be able to just use the stream as an async iterator https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator without this helper?
* Client uses ReadStream * Client uses WriteStream * delete port config lol * Disable everything for handler.test.ts * no void 0
* Client uses ReadStream * Client uses WriteStream * delete port config lol * Disable everything for handler.test.ts * no void 0
* Client uses ReadStream * Client uses WriteStream * delete port config lol * Disable everything for handler.test.ts * no void 0
* Client uses ReadStream * Client uses WriteStream * delete port config lol * Disable everything for handler.test.ts * no void 0
* Client uses ReadStream * Client uses WriteStream * delete port config lol * Disable everything for handler.test.ts * no void 0
* Client uses ReadStream * Client uses WriteStream * delete port config lol * Disable everything for handler.test.ts * no void 0
* Client uses ReadStream * Client uses WriteStream * delete port config lol * Disable everything for handler.test.ts * no void 0
All the changes are documented in `Protocol.md` but here's a summary: - Handle invalid client requests by sending a close with an error back - This was the main motivation for the change. While we could sort-of implement this error response without the other changes, things are setup in such a way where it is very hard to implement correctly without deeper changes in how we handle closing. - Add more robust closing mechanics - Half-close states - Close signals from read end of the pipes - Abort full-closure (for errors and cancellation) - Switch from `Pushable` and `AsyncIterator` APIs to a `ReadStream` and `WriteStream` - All procedures have `init` and some have `input` While the changes are not strictly backwards compatible, hence the major protocol bump, the system can still operate across versions to some extent. See PRs linked below for more information on the above # TODOs - [x] Define protocol and update doc #111 - [x] Design stream abstractions #118 - [x] Redsigned in #249 - [x] Implement stream abstractions - [x] ReadStream #130 - [x] WriteStream #132 - [x] All streams have init, some have input. - [x] Protocol change documented in #153 - [x] Implementation change #159 - [x] Use stream abstractions & implement protocol closing semantics - [x] Protocol: Implement close requests from readers #165 - [x] Protocol: Implement half-close - [x] Client #162 - [x] Server #163 - [x] Simple s/Pushable/Stream replacement - [x] Client #136 - [x] Server #137 - [x] Make `Input` iterator on the server use `Result` so we can signal stream closes, client disconnects, and aborts #172 - [x] Add Abort mechanism - [x] Docs update #175 - [x] Implement abort - [x] Client #193 - [x] Server #200 - [x] Add `INVALID_REQUEST` to schema #107 - [x] Handle/send back `INVALID_REQUEST` errors with an abort bit #203 - [x] Handle/send back `INTERNAL_RIVER_ERROR` with an abort bit #203 - [x] Send abort bit with `UNCAUGHT_ERROR` #201 - [x] Abort tombstones #204 - [ ] Try to find uncovered areas to test - [ ] `undefined` value for `init`, `input`, & `output`. - [ ] Update docs - [ ] Changelog --------- Co-authored-by: Jacky Zhao <[email protected]>
Why
More protocolv2 work #127
What changed
In this PR it's a simple replacement of
pushable
interface with stream interfaces, on the client-side. No protocol or API changes otherwise. Streams API is a superset ofpushable
, many of the stream methods aren't implemented correctly/don't make a lot of sense without further changes, but this is a good step.Versioning