joeycumines | 2 years ago | on: Show HN: Ts-Chan – Go-Like Concurrency Primitives for TypeScript/JavaScript
joeycumines's comments
joeycumines | 2 years ago | on: Show HN: Ts-Chan – Go-Like Concurrency Primitives for TypeScript/JavaScript
The one I slapped together works, but this one is better (fixes issues with actually stopping it properly): https://github.com/joeycumines/generator-ticker
On NPM as generator-ticker.
joeycumines | 2 years ago | on: Show HN: Ts-Chan – Go-Like Concurrency Primitives for TypeScript/JavaScript
Anyhow, do what you will. I don't get the impression that you are genuinely interested in this topic.
joeycumines | 2 years ago | on: Show HN: Ts-Chan – Go-Like Concurrency Primitives for TypeScript/JavaScript
joeycumines | 2 years ago | on: Show HN: Ts-Chan – Go-Like Concurrency Primitives for TypeScript/JavaScript
I'm not sure what specifically you were imagining, but I've added an example of how "vanilla JS" can achieve fan-in, using an AsyncGenerator: https://github.com/joeycumines/ts-chan/blob/main/docs/patter...
It uses one of the patterns suggested in a comment chain above, which I think is pretty neat, and wasn't one that readily occurred to me: https://news.ycombinator.com/item?id=38163562
I'm not making a case for using ts-chan for any situation where a simple generator-based solution suffices. I wouldn't call the example solution (in my first link) simple, but it's something I'd personally be ok with maintaining. Like, I'd approve a PR containing something similar without significant qualms, _if_ there was a significant enough motivator, and it was sufficiently unit tested. I might suggest `ts-chan` as an alternative, to make it easier to maintain, but wouldn't be particularly concerned either way.
That's all very subjective, though :)
joeycumines | 2 years ago | on: Show HN: Ts-Chan – Go-Like Concurrency Primitives for TypeScript/JavaScript
joeycumines | 2 years ago | on: Show HN: Ts-Chan – Go-Like Concurrency Primitives for TypeScript/JavaScript
joeycumines | 2 years ago | on: Show HN: Ts-Chan – Go-Like Concurrency Primitives for TypeScript/JavaScript
To be clear, I'm not saying "don't do any communication by sharing state", just that there are use cases where it's possible to make it much simpler to reason about.
As an example, you might control the state of "making a HTTP request to perform a search", within the frontend of a single page app that has a map, search filters, and results.
One strategy is to use a buffered channel (1 element), and, when the search filters are updated, drain then re-send the request to the channel.
The logic processing these requests would then just need to sit there, iterating on / receiving from the channel. It could also support cancellation, if that was desired.
(I'd imagine the results would be propagated via some other mechanism, e.g. to a store implementation)
joeycumines | 2 years ago | on: Show HN: Ts-Chan – Go-Like Concurrency Primitives for TypeScript/JavaScript
joeycumines | 2 years ago | on: Ask HN: Fan-in pattern in JavaScript, ts-chan docs, feedback requested
Based on feedback on my last post: https://news.ycombinator.com/item?id=38156519
I've been working on better documentation and examples, aimed at JavaScript developers without significant knowledge of concurrency-related patterns.
The first pattern I've covered is "fan-in". Aside from a side-by-side comparison, in the pattern doc linked in the question, I also implemented an example of the pattern, a "log aggregator", which multiplexes (TCP) log streams, formatting and writing out lines to a file. Details in the example readme: https://github.com/joeycumines/ts-chan/blob/main/examples/pa...
I'd appreciate it if you could let me know what you think, and if this is a step in a helpful direction.
Thanks :)
joeycumines | 2 years ago | on: Show HN: Ts-Chan – Go-Like Concurrency Primitives for TypeScript/JavaScript
I oversimplified my example perhaps - it also involved handling interruptions (certain system events), maintaining a lifecycle (set up and tear down), and scenarios where it allowed a certain subset of operations to be performed, while performing one of several operations. That last requirement was due to it using shell scripts to perform configuration of the system, and it needing to extract runtime and configuration information from the main daemon.
Still though, thanks very much for your comments, I've enjoyed reading them.
joeycumines | 2 years ago | on: Show HN: Ts-Chan – Go-Like Concurrency Primitives for TypeScript/JavaScript
I still like "pipelining" over that, but that can also be implemented with just an iterator, pretty trivially.
joeycumines | 2 years ago | on: Show HN: Ts-Chan – Go-Like Concurrency Primitives for TypeScript/JavaScript
To be clear, `ts-chan` is not intended to target any use case already addressed by promises or async/await.
You mentioned CSP so I'll assume you've got context re: that topic. I believe I understand your point re: synchronisation between threads, which is fair, but I'd point out that race conditions still exist in JavaScript - I'd even say they are common, at least in my experience. It is easiest to maintain the integrity of the internal state of complex data structures when only a single logical process can mutate that state at a time.
Example in a similar vein: Firewall daemon that accepts commands over RPC, and performs system configuration, in a linear, blocking fashion, to avoid blowing things up (say it runs `iptables` and/or `nft` commands, under the hood). It would be trivial to have a select statement, with a channel per command (or just one, perhaps), receiving the input payload. In JS, the response would probably be via callback, rather than a ping-pong channel recv then send, or the like.
It wasn't a firewall daemon (although it did interact with firewalld and more), but that's exactly a pattern I've implemented in Go, for a past employer. I don't imagine anyone is keen to implement such a thing in JavaScript, but it's a pattern that applies to anything that mutates state, especially if that state is fragile or complex.
joeycumines | 2 years ago | on: Show HN: Ts-Chan – Go-Like Concurrency Primitives for TypeScript/JavaScript
joeycumines | 2 years ago | on: Show HN: Ts-Chan – Go-Like Concurrency Primitives for TypeScript/JavaScript
I agree async iteration is pretty good - the `Chan` class implements both `Iterable` and `AsyncIterable`.
For quite a few scenarios, async generators are a better choice. They do have limitations, however. For example, you _can_ implement fan-in, but there's no easy mechanism to fan-in in a blocking manner, from sources that aren't known ahead of time. It's also hard to implement a "fair" mechanism, that doesn't bias certain inputs (like you might desire if multiplexing logs, for example).
joeycumines | 2 years ago | on: Show HN: Ts-Chan – Go-Like Concurrency Primitives for TypeScript/JavaScript
Fair call though, I guess. It doesn't really matter, but I'm certainly used to TypeScript and JavaScript.
joeycumines | 2 years ago | on: Show HN: Ts-Chan – Go-Like Concurrency Primitives for TypeScript/JavaScript
That's just something I copy and pasted from the documentation for the benchmark package I used. Allegedly, it is to prevent "certain compiler optimisations", which is something I'm familiar with when it comes to benchmarking Go code, for example.
I lack specific knowledge as to whether it's actually necessary, sorry :)
joeycumines | 2 years ago | on: Show HN: Ts-Chan – Go-Like Concurrency Primitives for TypeScript/JavaScript
JavaScript already supports concurrency, e.g. handling more than one HTTP request concurrently, despite the runtime being single-threaded in nature. Also provided by JavaScript is the ability to fork and join with other asynchronous tasks, e.g. using `Promise.all` to wait for multiple HTTP requests to complete.
The purpose of `ts-chan` is to make it easier to coordinate concurrent operations, via communication, which definitely isn't something JavaScript makes easy.
So part of this is addressing usability issues, and providing necessary boilerplate. I've modelled most of that after Go's channels.
Another is providing a mitigation for a common gotcha (well, it's gotten me), when attempting to implement behavior that involves multiple independent asynchronous operations, communicating with one another. Specifically, JS has a "microtask queue", an optimisation I believe was created to power async/await. Details / links to MDN here: https://github.com/joeycumines/ts-chan#the-microtask-queue-a...
joeycumines | 2 years ago | on: Show HN: Ts-Chan – Go-Like Concurrency Primitives for TypeScript/JavaScript
joeycumines | 2 years ago | on: Show HN: Ts-Chan – Go-Like Concurrency Primitives for TypeScript/JavaScript
I've dabbled in that too, though I don't actually use it for anything, currently: https://github.com/Mcsavvy/contextlib/pull/1
Hurt my head a little, but it's fixed now, and I'm at least moderately confident it's correct - unit tested the behavior step by step using `ts-chan`, actually. Will probably use that test as another example use case.