raunioroo
raunioroo3y ago

TTY vs console.log vs stdin and setRaw for dummies?

Hi all! Would someone be able to clear some things out with regards to deno inputs and outputs: - what exactly is one referring to, when talking about TTY? (in deno) is it just another name for console, or some of the std streams (stdin/stdout/stderr) - what about raw mode? there has been Deno.setRaw() but apparently removed in Deno 1.26. I think there was at some point a writer/reader/stream.setRaw() method or somesuch, but they maybe disappeared too. What is raw mode supposed to do, and can one enable it in the current Deno version somehow. - does deno do a lot of processing on console.log(stuff) versus writing raw bytes to std streams? What kind of processing, if any? And is the amount of processing the same whether deno is running on a windows terminal/vs code terminal, or as a child process of another deno process? - if there is a raw mode, does it apply to stream write, or just console.log? Asking because basically just wanting to learn. And I'm doing something that involves a lot of message passing (JSON lines) between deno processes/subprocesses. At the moment I'm just reading stdout stream to get messages back from child process, and writing to stdin.getWriter() to send messages. It's performing fine, but I anticipate the amount of messages will grow pretty big, and would like to make it as fast/lightweight as possible.
20 Replies
wulfey
wulfey3y ago
oh! i can help out in this one, one moment o when one says "tty" (short for teletype), they usually mean something with an input and an output, which is of course a terminal/console window o to understand raw mode (which affects the input only), it should be noted that for regular keypresses in "canonical" (not-raw) mode, they are, with their meanings, handled by the shell (such as letter presses, control keystrokes, arrows, special buttons...) essentially, raw mode disables that, and lets Deno (or any other command line application) read the actual bytes associated with the keypresses and handle them with its own logic (such as menus, special command line interfaces, custom features...) raw mode is faster than canonical mode, and gives you a ton of freedom with what keypresses can achieve (also, Deno.setRaw() was removed in favor of Deno.stdin.setRaw(), since it only really applies to the stdin)
raunioroo
rauniorooOP3y ago
oh, nice, makes sense!
wulfey
wulfey3y ago
o yes, console log does perform quite a bit of preprocessing (type conversions, custom formatting objects, syntax highlighting...) when running as a child process, however, im pretty sure console.log removes the color formatting part - it may be doing detection of what kind of output there is (file, tty, ipc...) , although im not quite sure though, one very important point to make
Asking because basically just wanting to learn. And I'm doing something that involves a lot of message passing (JSON lines) between deno processes/subprocesses. At the moment I'm just reading stdout stream to get messages back from child process, and writing to stdin.getWriter() to send messages. It's performing fine, but I anticipate the amount of messages will grow pretty big, and would like to make it as fast/lightweight as possible.
if you want to perform "inter-process communication", there are probably better (and faster!) ways to do so! i highly encourage you to look around for - be it plugins, or modules - which allow Deno to interact with more Deno
raunioroo
rauniorooOP3y ago
i see, setRaw() does exist in stdin indeed
wulfey
wulfey3y ago
in an earlier version it used to be Deno.setRaw(rid, state[, options]) i havent done much research for IPC (interprocess communication) but a quick google search lands this module ->>> https://deno.land/x/ipc@0.0.3 since its a 0.x.x module, i highly suggest you look around to see how it works and modify it to your needs
wulfey
wulfey3y ago
oh.
raunioroo
rauniorooOP3y ago
what would be better? i can think of local http/ws (slow) or perhaps unix sockets. or some more complex direct memory (shared memory magic?) i was thinking streams could be low level enough to keep things relatively simple.
wulfey
wulfey3y ago
well, actually, ipc can be done through unix sockets, which deno can
Deno.connect({ path: "./my-cool-socket.sock", "transport": "unix" });
Deno.connect({ path: "./my-cool-socket.sock", "transport": "unix" });
to
raunioroo
rauniorooOP3y ago
from quick look at the ipc module you linked, it seems to use unix sockets
wulfey
wulfey3y ago
creating those sockets may be achievable with something like Deno.listen, (but not sure!!) nope, not Deno.listen available on v1.28.3 oh of course it does, but its actually deprecated because deno can internally listen and create unix sockets though you can save yourself the pain of child processes by using those
wulfey
wulfey3y ago
forgive me, yes, it can be done using Deno.listen https://deno.land/api@v1.28.3?s=Deno.listen&unstable=
Deno
Deno.listen | Runtime APIs | Deno
Listen announces on the local transport address.
raunioroo
rauniorooOP3y ago
well, I got the child processes spawning and communication stuff pretty well working already, so that's not a problem. but if there is more performant option that streams, then its interesting.
wulfey
wulfey3y ago
unix sockets! i think those may be better (or at least way more straightforward) by the way, out of curiousity, what are you making?
raunioroo
rauniorooOP3y ago
might give sockets a try! i might wanna have later multiple child processes talking to each other directly, without going through the main process as a message broker of sorts. sounds like something that could also be maybe achievable with unix sockets Organizing my code/app into microservices kind of deal. Like, database access lives in one process, http server in another, etc. Then I can choose whether each service lives in a vanilla "in-process" object, or in a worker, or in a process, or on another server through HTTP/WS..
wulfey
wulfey3y ago
i see, thats nice also, may you never experience the hell that raw mode is sometimes (unless youre using it for something extremely simple)
raunioroo
rauniorooOP3y ago
fell in love with "subprocess services", especially for development, as 1) i can automatically restart a part that breaks, like deno panic, or mongo loses connection and can not gracefully reconnect, or whatever 2) monitoring of CPU, memory use of different parts of the program, also deno info to keep dependencies low. 3) automatically retry commands that fail 4) lazy load services on demand, so the app boots super quick, and heavy modules like anything that brings WASM or massive NPM dependencies are lazyload 5) automatically retry any commands that fail (first simply retry, then try rebooting the subprocess)
wulfey
wulfey3y ago
that sounds great i dont have much experience with subprocess stuff (since the only thing i work on are omegle group chats, which does not come near that) but either way, i sure do hope i helped out with some of your questions :)
raunioroo
rauniorooOP3y ago
you were great help, thank you! just to add, about the subprocess service thingamabob, two more things: 1) fine grained permissions control for each process/service, and 2) watch mode reboots SUPER quick and keeps all the other services state intact when only the changed service reboots on file change, that's super nice
wulfey
wulfey3y ago
alright, thank you! and if you need anything else, just @ me if im online
raunioroo
rauniorooOP3y ago
ty!