HNHacker News
TopNewBestAskShowJobs

sa46

1,425 karma · joined December 2, 2015

Building AI for distributors, contractors, and manufacturers.

Paratrooper to programmer.

http://github.com/jschaf

hn@schafer.dev

submissionscomments
sa46··on The Hare programming language
With cross compilation or docker for development, I'm not clear on why using Linux is a huge boon to developing servers. Having been down the path of Linux-for-all-things, these days I'd much rather have a nice, fast macbook.
sa46··on Ask HN: Do you use an optimization solver? Which one? Do you like it?
Related question, what are broad recommendations for vehicle routing with capacity, time windows, and a smattering of other constraints? I'm a generalist SWE by trade and my (shallow) survey of the field revealed:

General solvers:

- LocalSolver: good docs, reasonable pricing, docs make it sound fast

- ORTools: Open source, we we're leaning towards this since we're not doing anything incredibly fancy and it'd be nice to embed the solver in our server.

- Gurobi: major player in the space, will charge you an arm and a few legs.

Vehicle routing specific solvers were covered in absolutely outstanding detail by "Open Source Routing Engines And Algorithms – An Overview" [1].

We were leaning towards ORTools since we didn't want to get charged by number of jobs or compute. LocalSolver also seemed promising.

Also, is there a cost-efficient way to get distance matrices for ~50 stops? Google maps and Mapbox are wicked expensive. Is PostGIS reasonable?

[1]: https://gis-ops.com/open-source-routing-engines-and-algorith...

sa46··on How we upgraded our 4TB Postgres database
In-place is a separate concept from zero downtime. Similarly, an inplace upgrade of your OS doesn't mean you can continue using the OS during the upgrade; it means you get to keep your data without restoring from an external backup.

The benefit of an inplace upgrade for postgres is you don't have to spin up another server, restore from backup, and run pg_upgrade yourself.

sa46··on Static Site Generator in 86 Lines
That’s a sed-injection bug.
sa46··on Kim Jong-un stars in film of missile launch on North Korean TV
A interesting question to ponder is how and why you would mandate training for a various task across a large organization while balancing constraints of maintaining readiness, accomplishing other mandated training, equipment availability, and minimizing training injuries.

An Army War College study made waves a few years because it found:

> that many Army officers, after repeated exposure to the overwhelming demands and the associated need to put their honor on the line to verify compliance, have become ethically numb. As a result, an officer’s signature and word have become tools to maneuver through the Army bureaucracy rather than being symbols of integrity and honesty. [1]

In that light, if I were rolling out a combatives program I’d focus on the physical training and mental toughness benefits rather than the increased lethality in hand-to-hand combat.

[1]: https://press.armywarcollege.edu/monographs/466/

sa46··on NYC allows citizens to report idling vehicles in exchange for a cut of the fines
I suspect the overwhelming majority of crime reporting is citizens reporting other citizens, i.e. calling 911.
sa46··on Fuchsia IDL Overview
How does backwards compatibility work in FIDL? I'm familiar with protobufs which allow:

- Renaming a field: Does FIDL rely on the traversal order for stable IDs?

- Converting the type of any field backed by a varint to any other varint field (bool, ints)

- Converting a singular field to a repeated field.

sa46··on FoundationDB: A distributed unbundled transactional key value store
Very curious, what’s an alternative implementation strategy or more appropriate mental model?

My mental model (I am not a database engineer) is that every SQL database is fundamentally backed by a key value store. For Postgres, each value is a row of a relation, the key is the relation’s key, and the physical storage is the table file. Postgres builds b-trees on top to make it fast, but the b-tree itself is a relation, a key value store that Postgres works hard to keep sorted.

sa46··on What Google search isn’t showing you
I’ve thought about creating HN Tropes, similar to TV Tropes to categorize the repetitive discussions with comments that are easily predicted. I haven’t convinced myself it’d help things, might just fuel the fire.
sa46··on Ask HN: Who is hiring? (March 2022)
SimpleCircle | Senior Engineer | San Francisco | Full-time | ONSITE

SaaS ERP for craft breweries to scale up delivery and operations.

Join us as an engineer at our seven-person, fully funded startup serving craft breweries. We’re looking for senior engineers well-versed with the intricacies of building rich, data-backed applications. You will develop and architect a greenfield ERP for breweries from the ground floor and help shape a world-class engineering team.

Tech stack:

  - React & Typescript

  - Go backend using gRPC (actually Twirp)

  - Postgres

We’re based in SF in the Mission (neighbors with Smitten Ice Cream).

careers@simplecircle.io (or email my profile)

sa46··on Ask HN: Tools to visualize data in SQL databases?
Not sure about Preset specifically, but most SaaS vendors advertise their IP address so you can limit incoming database connections to the SaaS vendor’s IP address.
sa46··on Nuanced communication usually doesn't work at scale
Mission command [1] might be useful here. The main idea is you state the mission and your expanded intent and each subordinate command does the same thing all the way down the chain.

There’s several “checksums” commonly employed in the US Army. The subordinate command’s orders will contain the verbatim mission statement (typically one sentence with the five whys) from the both their commanding unit and the next level up. The order also includes the expanded intent from their commanding unit. Finally, a commander will require back briefs from subordinate commands to make sure plans align.

[1] https://en.m.wikipedia.org/wiki/Mission_command

sa46··on I’m porting the TypeScript type checker tsc to Go
I think it's okay not to get near 1:1 parity given the amount of unchecked type-casts (foo as unknown as X) and ts-ignores that happen anyway in most code bases. The other advantage is that the typechecker is advisory, meaning the code will run (and might explode) but it will run even if the types are wrong since compiling typescript is mostly just throwing away the type info.
sa46··on Tips for making writing more fun
Though it's a rather deep rabbit hole to get Tufte-style side notes [1]. Crafting Interpreters does it quite nicely [2].

[1]: https://www.gwern.net/Sidenotes

[2]: https://craftinginterpreters.com/statements-and-state.html

sa46··on Dura is a background process that watches your Git repositories
Local history saves my bacon about once a month. It's incredibly helpful as it lets me adopt a fearless refactoring approach knowing that I can always get back.
sa46··on The argument against clearing the database between tests (2020)
Nice catch, that was a neat rabbit hole [1]! I run an Ubuntu derivative so you're correct that /tmp is not mounted using tmpfs. Looks like Arch and Fedora use tmpfs and the Debian flavors do not.

[1]: https://lwn.net/Articles/499410/

sa46··on The argument against clearing the database between tests (2020)
If we could wave a medium-sized magic wand to make the database fast for tests (as least as fast as the proposed alternative), would we still use a single shared database for all tests? I would use a separate database per test since I don't find the arguments about realistic data shape convincing.

Back the real world: since the database isn't fast, we can either make the test infrastructure faster or hoist the problem into the application domain by using tricks like the OP. I'm a platform engineer at heart so I lean towards making the infra faster in order to accelerate app development.

My hot take is that developers are too comfortable with slow test databases and we're due for an "esbuild moment". With appropriate elbow grease, some databases, like Postgres, can be quite speedy (~300ms to start a cluster for a suite and ~40ms per test). The main tricks:

- Avoid Docker. Postgres is cross platform and Docker on macOS is sloooow.

- Create a single database cluster (Postgres lingo). Initialize a fresh database in the cluster with the seed data. Use that database as a template for all future tests. Creating from a template was 12x faster than creating from scratch in a benchmark I ran.

- Use a ram-backed file system. Using /tmp is probably good enough since its backed by tmpfs which should use RAM for small files.

- Disable fsync for the database.

I wrote up a more detailed take for Postgres here: https://news.ycombinator.com/item?id=28472062.

sa46··on Databases in 2021: A Year in Review
In Postgres land, I think most businesses work around temporal tables with audit tables using triggers to dump jsonb or hstore. I wrote up how I used table-inheritance here [1].

I agree with your point. Postgres is starting to stick out compared to alternatives:

- MS SQL supports uni-temporal tables using system time.

- Snowflake has time travel which acts like temporal tables but with a limited retention window. Seems more like a restore mechanism.

- MariaDB has system-versioned tables (doesn't look like it's in MySQL).

- Cockroach DB has uni-temporal support with system time but limited to the garbage collection period. The docs indicate you don't want a long garbage collection period since all versions are stored in a single range.

- Oracle seems to have the best temporal support with their flashback tech. But it's hard to read between the lines to figure out what it actually does.

[1]: https://news.ycombinator.com/item?id=29010446

sa46··on Ubisoft's unprecedented “exodus” of developers
Just as developers are responsible for the codebase. Yet folks seem rather receptive to the concept of technical debt. It’s not much of stretch to imagine organizational debt caused by pesky human problems.
sa46··on Ask HN: How do you manage direct updates to databases in a production system
What happens when prod is a few hundred terabytes or you use logical replication to stream changes to handle major version updates? The GP’s point was shipping 100% of a large database isn’t feasible.

You’re conflating dev environments with restoring backups. Those can be the same thing but are often separate.

sa46··on Wolfram Cloud
There’s a fun estimation technique from Programming Pearls: pi seconds is a nano century. So, 3.14e7 seconds in a year.

    80 bytes/sec * 3.14e7 sec = 2.4e9 bytes

http://wordaligned.org/articles/pi-seconds
sa46··on Professional maintainers: a wake-up call
Databases aren't a great example. There's a rich landscape of non open-source databases that provide features not available in open-source DBs. Cockroach DB, Spanner, SingleStore, Vertica, Snowflake.
sa46··on How to write idempotent Bash scripts (2019)
You can use a combination of `comm` and `uniq` to implement set intersection and union. https://ss64.com/bash/comm.html

> Return the unique lines in the file words.txt that don't exist in countries.txt

    comm -23 <(sort words.txt | uniq) <(sort countries.txt | uniq)
>Return the lines that are in both words.txt and countries.txt:

    comm -12 <(sort words.txt | uniq) <(sort countries.txt | uniq)
sa46··on AWS – The YAML Way
- Define a new file format, yaml-plus.

- Create a parser for the new yaml-plus format across all supported languages.

- Migrate all build processes to handle yaml-plus with the new parser. In a large-org, it's likely impossible to track down all the usages of YAML. Someone will have a bash script that hasn't been touched for 10 years that implements an adhoc YAML parser.

- Modify the YAML mode for all supported editors to support the new syntax.

This doesn't sound like minimal effort. Mandating that all new configs must be JSON (or similar, newer alternative like cue) is way easier since JSON already exists.

sa46··on Our journey in dropping the ORM in Go
> Do you write out 120 "INSERT" statements, 120 "UPDATE" statements, 120 "DELETE" statements as raw strings

Yes. For example: https://github.com/jschaf/pggen/blob/main/example/erp/order/....

> that is also using an ORM

ORM as a term covers a wide swathe of usage. In the smallest definition, an ORM converts DB tuples to Go structs. In common usage, most folks use ORM to mean a generic query builder plus the type conversion from tuples to structs. For other usages, I prefer the Patterns of Enterprise Application Architecture terms [1] like data-mapper, active record, and table-data gateway.

[1]: https://martinfowler.com/eaaCatalog/

sa46··on Our journey in dropping the ORM in Go
Having written a non-ORM Go-Postgres tool [1] similar to sqlc, I'm a big fan of this article, especially their acknowledgment that using SQL moves the eng culture towards data-centric engineering. Some thoughts:

- Application code should not rely on database table structure (like the ActiveRecord pattern). Modeling the database as a bunch of queries is a better bet since you can change the underlying table structure but keep the same query semantics to allow for database refactoring.

- Database code and queries should be defined in SQL. I'm not a fan of defining the database in another programming language that generates DDL for you since it's another layer of abstraction that usually leaks heavily.

- One of the main drawbacks of writing queries in plain SQL is that dynamic queries are more difficult to write. I haven't found that to be too much of a problem since you can use multiple queries or push some of the dynamic parts into a SQL predicate. Some things are easier with an ORM, like dynamic ordering or dynamic group-by clauses.

[1]: https://github.com/jschaf/pggen

Similar comment from a few months ago comparing Go approaches to SQL: https://news.ycombinator.com/item?id=28463938

sa46··on How We Turn Authorization Logic into SQL
I haven’t seen any Postgres plugins that extend RLS but very interested. Any links?
sa46··on Living with single-tenant and multi-tenant architectures
Can you clarify? You can vertically scale a database a few orders of magnitude. My view is that “some point” is a long way off for most OLTP workloads.
sa46··on Tree Sitter and the Complications of Parsing Languages
I'm not familiar with state of the art for language servers but here's common IntelliJ refactors I use across Go and TypeScript (and Java a while ago):

- Add a parameter to a method signature and fill it in with a default value.

- Reorder method parameters.

- Extract a block of code to a method that infers the correct input and output types.

The most advanced refactoring I've done with IntelliJ is structural replace for Java which can do something like: for every private method matching the name "*DoThing" defined on a class that extends Foo, insert a log line at the beginning of the method: https://www.jetbrains.com/help/idea/structural-search-and-re...

I make heavy use of the "integrated" aspect of IntelliJ. One of the nicer benefits is that SQL strings are type-checked against a database schema.

sa46··on Back to basics: Writing an application using Go and PostgreSQL
Dynamic queries are difficult to model when starting from a static query since SQL doesn't compose well. The workarounds I've used:

- Use multiple queries that share the same output type.

- Push the predicate into the query directly.

However, you can't pass an expression for an order by column since the order by clause takes a name, not an expression. Postgres doesn't allow using names as arguments to a prepared query so that leaves either adding an annotation like sqlc.order_by that's dynamically added to a query string, or by getting more creative with the structure of the query:

    SELECT * FROM AUTHORS WHERE sqlc.arg('by_date') ORDER BY DATE
    UNION ALL
    SELECT * FROM AUTHORS WHERE NOT sqlc.arg('by_date')
← PreviousPage 8 of 15Next →