Mihai Târnovan

579 posts

Mihai Târnovan banner
Mihai Târnovan

Mihai Târnovan

@mtarnovan

Inscrit le Temmuz 2009
139 Abonnements97 Abonnés
TextQL
TextQL@TextQL·
🚀Shipping fast but drowning in SQL? Plug Ana (our AI data-scientist) straight into your Supabase in 60 sec: • Ask in plain English → get charts, forecasts, action items • Auto-generated docs & playbooks land in Slack/email • Free founder tier so you can keep vibe-coding
English
13
8
51
15K
Douglas Correa
Douglas Correa@douglas_correa·
I'm returning to @elixirlang and testing Tidewave Web from @dashbit/@josevalim. It's surprising how it offers a unique coding agent experience, like a @v0 tailored to your stack, with point, click, and prompt features. It integrates with your backend, database, and more, enabling not only dev/ui tasks but also interacting with DB, etc. It brings new ideas for interacting with code via a coding agent. Excited to dive back into Elixir and explore it!
English
2
5
36
3.3K
Mihai Târnovan
Mihai Târnovan@mtarnovan·
@bro_abra @PromptLLM Not to be pedantic, but it does not "understand" anything. Doesn't mean it's not useful ofc, but it's dangerous to rely on it without developing sort of a spidy-sense for when it can be wrong / hallucinate etc.
English
1
0
2
41
no
no@bro_abra·
@PromptLLM @mtarnovan how many times have you spent the time to check what "grok is this true" gives back? most of times the devil is in the details and grok does not bother. it does not understand nuance.
English
1
0
2
49
Prompter
Prompter@PromptLLM·
A sign someone is low IQ is when they say “AI will make us dumb.” It really couldn’t be further from the truth You have the ability to learn anything you ever wanted, taught to you in a way tailored to your brain, from your pocket. The ideas and concepts I am now aware of and now enter my thought patterns 100x then what it was pre AI. It’s crazy how small minded people are with what they can do with AI. They only think of it through a business / financial lense, and don’t realise how it can enrich other areas of their life.
English
12
13
110
10.1K
Mihai Târnovan
Mihai Târnovan@mtarnovan·
@PromptLLM Emphasis was on "reflexive", what I meant by that is they replace their own critical thinking with grok's, often don't even bother to analyse the response, just taking it at face value. To me that *is* a way to make yourself dumber by overrelying on AI.
English
0
0
0
15
Prompter
Prompter@PromptLLM·
@mtarnovan I’d argue the “grok is this true?” Shows people using AI to help them learn more
English
2
0
0
166
José Valim
José Valim@josevalim·
Tidewave Web for Rails and Phoenix is coming! If you want to be the first to know, visit tidewave.ai, join our Discord or our waiting list!
José Valim tweet media
English
2
16
167
16.2K
Mihai Târnovan
Mihai Târnovan@mtarnovan·
@ryanwinchester @VictoriqueM No offense, but you're just calling a lib, which is itself just a wrapper around another lib, which is written in Rust. So how is that "parsing in elixir"...
English
0
0
0
11
Victoria
Victoria@VictoriqueM·
Just finished the Billion Row Challenge in Go. Had to process a billion temperature readings and honestly the whole thing was a pain in the arse but whatever So the problem is you've got this 14GB file with a billion lines and you need to calculate min/max/average temps for each weather station. Most people probably just read the file normally like idiots so I figured I'd do something less stupid. Fuck reading files the normal way. I wrote custom memory mapping using raw syscalls because copying 14GB into RAM is stupid and if you do it, you should feel bad. Just map the entire cunt directly into virtual memory. Had to write separate implementations for Unix and Windows because apparently I hate myself. The Windows CreateFileMapping API is particularly annoying but whatever, it works (and seems to actually be faster than Unix). The tricky bit was splitting this massive file across CPU cores without cutting lines in half like a numbnuts. Had to write logic that finds newline boundaries so each worker gets a clean chunk to process. Boring but necessary. Threw out the entire Go string parsing library and wrote my own temperature parser that makes a bunch of assumptions and probably breaks on edge cases. But it's fast as shit and handles the expected format fine so who cares. The parallelization is pretty straightforward - spawn one goroutine per CPU core, let them tear through their chunks, then merge all the results at the end. No fancy synchronization needed, just raw parallel processing. Each worker maintains its own map of station stats then I combine everything once they're done. The whole thing processes like 400 million rows per second and reads data at 5+ GB/s which is apparently fast. Zero external dependencies because I am either too much into code or i am too egotistic and the Go stdlib is good enough for this shit. Just syscalls and some creative abuse of unsafe pointers. Also built a data generator that creates realistic test files with actual weather station names. That was almost more annoying than the actual challenge because generating a billion rows of realistic data takes forever. The cross-platform stuff was tedious was a bit shit - different memory mapping APIs, different file handling, different everything. But now it runs on whatever so I guess that's something, does this mean it's not ENTIRELY cross compatible? i tested it with linux, windows and macos ARM and it all works fine Anyway it works and it's fast and I'm done thinking about parsing temperature strings for a while. 15 seconds to generate and about 4.8 to parse, considering that the fastest Java version i could find that didn't fuck around with some low level assembly was 10 seconds, i think it's not bad for 2 hours or so of coding.
Victoria tweet mediaVictoria tweet media
Walker Boh@nakedMCSE

Processing a billion rows in python. Three and a half minutes, not bad for python. Naive implementation took ten minutes lol

English
62
116
1.8K
206.8K
Mihai Târnovan retweeté
José Valim
José Valim@josevalim·
Congrats to Rust, Gleam (welcome!!) and Elixir on being the top 3 most admired languages on the StackOverflow Survey and Phoenix for being the most admired web framework for the third year in a row! survey.stackoverflow.co/2025
English
8
122
807
35.8K
Lucian Parvu
Lucian Parvu@lucianparvu·
Love this credo setting. I think it should be default when using agentic coding tools. I have seen code changed into pieces hard to understand after failing credo checks using the default value source: @AshFramework ash_phoenix repo - github.com/ash-project/as… #elixirlang
Lucian Parvu tweet media
English
2
0
7
266
Mihai Târnovan
Mihai Târnovan@mtarnovan·
@jh3yy This does have a downside though as inert content is not searchable in the browser, so maybe not the best for a side nav?
English
1
0
0
348
jhey ʕ•ᴥ•ʔ
jhey ʕ•ᴥ•ʔ@jh3yy·
CSS sidebar tricks 🤌 transition expanded menu items to "auto" height using grid li > div[inert] { grid-template-rows: 0fr; } li > div { grid-template-rows: 1fr; transition: grid-template-rows .3s; }
English
30
166
2.7K
117.1K
Mihai Târnovan
Mihai Târnovan@mtarnovan·
@MKBHD Is this an anti-captcha, meant to block humans and only let AIs pass?
English
0
0
0
12
José Valim
José Valim@josevalim·
Dear Elixir uses, I need your numbers. Start your project with "iex -S mix" and then run this: iex(1)> app = Mix.Project.compile_path() |> Path.join("#{Mix.Project.config()[:app]}.app") iex(2)> :timer.tc(:file, :consult, [app]) |> elem(0) iex(3)> File.ls!(Mix.Project.compile_path()) |> length() Reply with the results of lines 2 and 3.
English
111
22
140
28.8K
Mihai Târnovan retweeté
Manuel Kallenbach
Manuel Kallenbach@manukall·
Ich hab was gebaut: Auf taschenbuchalarm.de könnt ihr euch benachrichtigen lassen, wenn euer Wunschbuch als Taschenbuch erscheint. Mir sind die gebundenen Bücher oft zu teuer, aber wenn sie dann als Taschenbuch erscheinen, hab ich sie schon wieder vergessen.
Deutsch
0
1
4
127
Mihai Târnovan retweeté
Howard Lince III
Howard Lince III@HowardL3·
A 9.9 CVE has been announced for Linux 👀 Remote code execution. No details yet. Heartbleed was 7.5, for reference. This is one of the worst in history. All GNU/Linux systems impacted.
English
152
1.1K
8.4K
1.2M
Mihai Târnovan
Mihai Târnovan@mtarnovan·
@accomazzo @OndrejValenta3 @elixirlang Curious why not? To me this seems like a lot of complexity for something you get for free if you cluster your nodes. Also, not clustering seems to miss out on a lot of what Erlang/OTP has to offer 🤔
English
0
0
0
45
Anthony Accomazzo
Anthony Accomazzo@accomazzo·
@OndrejValenta3 @elixirlang In OTP, you can use :global.mutex in place of Redis in this design You can also use named processes/registries But didn’t work for us, as those require clustering. And we don’t eg cluster new nodes to old ones during deploys
English
1
0
2
140
Anthony Accomazzo
Anthony Accomazzo@accomazzo·
Mutexes are an essential tool in distributed systems. We have a mutex pattern we use when we really want to be sure a given @elixirlang GenServer is only running at most once in our system. While the implementation is unique to Elixir, the principles can be applied anywhere. I like a Redis-based solution for this. Redis works even if your nodes are not clustered. And it also works for deploys where you're bringing up new nodes that are not clustered to your current nodes. The end result of our solution is MutexedSupervisor. Assuming you have some GenServer called MyExclusiveServer, you can add this line to your supervision tree like this: MutexedSupervisor.child_spec(MyApp.MutexedMyExclusiveServer, [MyApp.MyExclusiveServer]) and be confident `MyExclusiveServer` will only ever be running once in your system. Here's how it works: MutexedSupervisor We'll start at the top and work our way down the tree. The body of MutexedSupervisor looks like this: MutexedSupervisor is a supervisor with the `one_for_all` strategy. You boot it with a list of `child_specs`, or the list of processes that ought to be booted when the Supervisor acquires a mutex. (The Module.concat/1 calls aren't too important, just how we create unique names for the various servers.) MutexedSupervisor has two children: - ChildrenSupervisor: This supervisor is a vanilla supervisor defined elsewhere in the file. It starts up with no children. But it will be the supervisor under which we boot the child processes passed in via `child_specs` (i.e. `MyExclusiveServer` will live under `ChildrenSupervisor`). - MutexOwner: This is a GenStateMachine that we'll look at next. Its sole job is to acquire a mutex and keep it. As we'll see, when MutexOwner acquires a mutex, it will call `on_acquired`. That invokes the `start_children` function, which boots the `child_specs` under ChildrenSupervisor. The `mutex_key` should just be a unique string for the GenServer you want to mutex. e.g. `"myapp:mutex:#{env()}:my_exclusive_genserver"` Importantly, if the MutexOwner somehow loses the mutex (which, if everything is setup properly, should basically never happen), it will shutdown. That will in turn take down the ChildrenSupervisor. When everything comes back up, the MutexOwner will need to re-acquire the mutex before any children are booted. The MutexOwner is a linchpin in this process, so let's look at that next. MutexOwner MutexOwner is a GenStateMachine (a special flavor of GenServer). We want MutexOwner to behave like this: 1. Boots up in an `await_mutex` state, tries to acquire the mutex. 2. It's able to acquire a mutex if the Redis key is not set to some value. In that instance, it acquires the mutex by setting the key to a `mutex_token`. A `mutex_token` is a random UUID that it generated on boot. 3. It's important that when it acquires the key, it sets an expiry on it. That way, if it somehow dies without releasing the key, the mutex isn't "stuck" in its possession. 4. Therefore, after acquiring the mutex, it must continuously "touch" the key by resetting the expiry. 5. If when it goes to touch the key the key was inexplicably taken from it (i.e. `mutex_token` is set to some other value), it will crash. When MutexOwner acquires the mutex, it calls `on_acquired`, booting the children in MutexedSupervisor. If it loses the mutex, it crashes, ensuring that the children of MutexedSupervisor stop as well. So, here's how we implement that behavior. The GSM boots in the `await_mutex` state and immediately fires the `acquire_mutex` timeout: In the `acquire_mutex` handler, it attempts to acquire the mutex. If it does, it calls the `on_acquired` function. Then, it queues up the "keep" timer that will fire in a few seconds to keep the mutex. Its next state switches to `has_mutex`: If it doesn't acquire the mutex, it simply re-enqueues the `acquire_mutex` timer. We'll look at how it acquires a mutex in a moment. But first, this is how it keeps the mutex: It will also attempt to release the mutex in `terminate`. This is nice, as then other processes don't have to wait for the mutex to expire. A fine expiry/timeout for the mutex is on the order of ~5 seconds. Mutex To acquire a mutex and keep a mutex, the MutexOwner calls `Mutex.acquire_or_touch`: Mutex.acquire_or_touch(data.mutex_key, data.mutex_token, data.lock_expiry) To build our mutex with Redis, we need some Lua. Here's what the Lua script looks like: if redis.call("GET", KEYS[1]) == ARGV[1] then redis.call("PEXPIRE", KEYS[1], ARGV[2]) return ARGV[1] elseif redis.call("EXISTS", KEYS[1]) == 0 then redis.call("SET", KEYS[1], ARGV[1], "PX", ARGV[2]) return ARGV[1] else return redis.call("GET", KEYS[1]) end We're using a basic Redis key/value. The algorithm here: 1. If the current value at mutex_key is equal to the mutex_token, top off the expiry of the key. This is how the MutexOwner touches the key to keep the mutex. 2. If the key is not set to any value, then the mutex_key is available. Therefore, claim the key by setting the value to our mutex_token and set an expiry. 3. Otherwise, the mutex_key is taken by another process. We return the value (unused, can be helpful for debugging). Putting it all together + the code With those building blocks, you can build an API where you can add exclusive GenServers to your app with a single line: MutexedSupervisor.child_spec(MyApp.MutexedMyExclusiveServer, [MyApp.MyExclusiveServer]) Check out the source code to see more. MutexedSupervisor: github.com/sequinstream/s… MutexOwner: github.com/sequinstream/s… Mutex: github.com/sequinstream/s…
Anthony Accomazzo tweet mediaAnthony Accomazzo tweet mediaAnthony Accomazzo tweet mediaAnthony Accomazzo tweet media
English
8
6
71
4.7K