The title of the article is "Micro-libraries need to die already". Renaming the submission to "Micro-libraries should never be used" is pathetic, Daniel. I'm not surprised though.
HN user
nalgeon
antonz.org
I appreciate your comments, and thank you for trying out the extension.
This query returns -1 (minus one, not one), which seems correct to me. The first date is before the second:
select time_compare(
time_date(1927, 12, 31, 23, 58, 08, 0, 28800000),
time_date(1927, 12, 31, 23, 58, 09, 0, 28800000)
);
-1Thanks for the suggestion! True, only fixed offsets are supported, not timezone names.
Storing unix timestamp as nanoseconds is not Go's style, but you can do just that with this extension.
select time_to_nano(time_now());
-- 1722979335431295000If the result exceeds the maximum value that can be stored in a Duration, the maximum duration will be returned.
It works very well for me and thousands of other Go developers. That's why I chose this approach.
If you find the official release notes a bit dry (they really are), I've prepared an interactive version with lots of examples:
- Iterators (range / types / pull / slices / maps).
- Timer changes (garbage collection and reset/stop behavior).
- Canonical values with the `unique` package.
- HTTP cookie handling.
- Copying directories.
- Slices and atomics changes.
Thank you, glad you like it! In fact, one of the reasons I started Codapi in 2023 was to have a playground for an interactive book on Go concurrency.
I got a bit carried away with Codapi and later Redka (Redis+SQLite), but eventually returned to the book :)
Context in Go is (mostly) a tool for canceling operations. There will be a chapter on contexts in part 1 of the book.
Educative also has a very strange (to say the least) way of interacting with authors: https://antonz.org/educative
Thanks, Michael! I think it's pretty clear even without it :)
Codapi works with mkdocs (and basically any other static generator).
Here is the JS widget and integration guides:
I like to explain things by example, and interactive examples are even better. So I built a sandbox server that lets you run virtually any software. And a widget to easily add interactive code examples to any kind of technical documentation.
You can use it to build your own sandboxes, or use existing ones to write interactive guides like these: https://github.com/nalgeon/tryxinyminutes
Sure! I really like your writing.
It works with redis-py (which python-rq uses), but I doubt it will be any good in this case. python-rq seems to use Lua scripting in Redis, which is not planned for 1.0. I'd rather not add it at all, but we'll see.
The goal is to have a convenient API to work with common data structures, with an SQL backend and all the benefits it provides. Such as:
— Small memory footprint even for large datasets.
— ACID transactions.
— SQL interface for introspection and reporting.
Great tips, thank you! The thing is, getting maximum throughput is not the goal of the project (at least not at this stage). I'm using reasonable SQLite defaults (including WAL), but that's it for now.
Thank you! I also think that the relational model can get you pretty far if you don't need to squeeze every last bit of performance out of the program. And the added benefit of using a battle-tested SQL engine is far fewer storage-related bugs.
Thought about it, decided to start with simpler and good enough option. The goal here is not to beat Redis anyway.
Yeah, it's explained in the code[1]
SQLite only allows one writer at a time, so concurrent writes will fail with a "database is locked" (SQLITE_BUSY) error.
There are two ways to enforce the single writer rule:
1. Use a mutex for write operations.
2. Set the maximum number of DB connections to 1.
Intuitively, the mutex approach seems better, because it does not limit the number of concurrent read operations. The benchmarks show the following results:
- GET: 2% better rps and 25% better p50 response time with mutex
- SET: 2% better rps and 60% worse p50 response time with mutex
Due to the significant p50 response time mutex penalty for SET, I've decided to use the max connections approach for now.
[1] https://github.com/nalgeon/redka/blob/main/internal/sqlx/db....
Can't fit everything in 1.0, has to start with something. If the community is interested in the project, there will be more.
I'm a big fan of both Redis and SQLite, so I decided to combine the two. SQLite is specifically designed for many small queries[1], and it's probably as close as relational engines can get to Redis, so I think it might be a good fit.
Did I?
Both in-process (Go API) and standalone (RESP) servers.
In-process means that the database is "embedded / clientside" in your terms.
There's also an interactive "Git by Example" guide I recently wrote on a similar topic. It has a playground for each of the commands mentioned in Martin's article (and many others):
— switch
— restore
— sparse-checkout
— worktree
— bisect
It's good to know I'm not the only one who has trouble with basic logical reasoning!
Definitely not "simple code is stupid".
You are literally living the dream!
I never said anything like that in the post. And I never said that writing simple code is stupid.
The most healthy approach is probably to compare yourself to yourself N years ago, not to others. Comparing yourself to others will always leave you disappointed.
But it's easier said than done. Especially if you read HN :)
Working like this typically creates additional cognitive load because you have to constantly convince yourself that it's okay, you can handle it, it's just a job, etc. It also increases the risk of burnout.
So yeah, it's a pretty tough deal.