HN user

john-shaffer

595 karma

https://github.com/john-shaffer

hn.scorn217@passmail.net

Posts6
Comments192
View on HN
Infinite Craft 2 years ago

Mostly playing around with stacking "powerful" words:

  King Kong + Power Ranger = King Kong Ranger (first)
  Megazord + Power Ranger = Power Megazord
  Megazord + Power Megazord or Artzord + Megazord = Ultrazord
  Dragonzord + Art = Artzord (first)
  Groot + Mega Artzord = Grootzord
  Megazord + Grootzord = Gigazord (first)
  Godzord + Giga Artzord = Giga Godzord (first)
  Giga Godzord + Giga Titanic Gigazord = Giga Titanic Godzord (first)
  Giga Titanic Godzord + Mega Power Godzillazord = Super Giga Mega Titanic Power Godzillazord (first)
I also got firsts on both Earthquake Laser and Laser Earthquake, but I'm not sure what the recipes were.

Trying to get Zebra was an interesting sequence.

  Tamer + Africa = Tamerlane (first)
  Tamerlane + Terror = Timur (first)
  Timur + Asia = Genghis Khan
  Genghis Khan + Bellerophon = Alexander the Great
  Alexander the Great + Unicorn = Bucephalus (first)
  Alexander the Great + Bucephalus = Horse
  Horse + Africa = Zebra

Clojure itself actually loads pretty quickly, but almost every project has enough libraries to make loading the project take a few seconds.

  export LC_ALL=C
  nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/2322899a1fa85f6547004b2829af81e7b444f506.tar.gz -p openssh
  ssh -V
  OpenSSH_6.1p1, OpenSSL 1.0.0i 19 Apr 2012
Note that the first stable release of nixpkgs was in 2013.

DVC is slow because it stores and writes data twice, and the default of dozens of concurrent downloads causes resource starvation. They finally improved uploads in 3.0, but downloads and storage are still much worse than a simple "aws s3 cp". You can improve pull performance somewhat by passing a reasonable value for --jobs. Storage can be improved by nuking .dvc/cache. There's no way to skip writing all data twice though.

Look for something with good algorithms. Xethub worked very well for me, and oxen looks like a good alternative. git-xet has a very nice feature that allows you to mount a repo over the network [0]

[0] https://about.xethub.com/blog/mount-part-1

Performance with Docker is slightly worse, but it shouldn't be an issue for a long-running process. The main problem I've run into is that, by default, Docker logs will eventually fill the disk and crash the server. You have to change the logging system and then delete and recreate all of your containers, because there is no way to change the logging system for existing containers.

I have no affiliation, but I tried the free trial of their tool and I found that the Code Health metrics made a lot of sense. The files that it pointed out are definitely overly complex and more difficult to change than they need to be. But it gave perfect scores to some files with complex jobs that are better-designed. I recommend just giving it a spin on a codebase that you are very familiar with.

In production, I may only want one connection pool to a DB, and in that case global state is pretty much equivalent to passing state as an argument. Development in a Clojure REPL is a different story. I have one connection pool for the dev server, and a separate pool to run tests against. The test db is re-created from a template between each test run, without affecting the dev db at all. I can trivially have multiple test pools if I want to run tests concurrently.

I also have a separate service that the server makes calls to, which doesn't run on this server in production (it has its own production server), but does run in dev and test. Each dev/test system runs a separate instance of this service, which has its own separate connection pool(s), and setting this up was trivial.

Needless to say, failures are reproducible and meaningful. There is no mocking -- we test against real local services with real local DBs. (There are still some remote service calls which I'm slowly replacing, and some flakey, unavoidable remote dependencies in a few browser tests).

I didn't do anything special to make this possible other than naming the config files "service-name-config" instead of just "config". It is just the natural result of passing state in explicit arguments. The same is not true of global state.

Clojure is strongly typed and dynamically typed, not "untyped". Much of its core behavior is built on interfaces like ISeq.

It's not uncommon to use a spec library like clojure.spec or malli, whose benefits overlap those of static typing. I'm not sure if there is a measured improvement from their use, but they have either advantages like facilitating generative testing that do help one to write more correct software.

This is a good example of why dynamic vars are dangerous. They are just as perilous as global state, but are more surprising and more difficult to understand. Prefer passing explicit arguments in all cases. You don't have to even think about the behavior, and you'll never spend 8 hours tracking down a missing binding in a commit from 2018.

You might be just fine adding an unindexed tsvector column, since you've already filtered down the results.

The GIN indexes for FTS don't really work in conjunction with other indices, which is why https://github.com/postgrespro/rum exists. Luckily, it sounds like you can use your existing indices to filter and let postgres scan for matches on the tsvector. The GIN tsvector indices are quite expensive to build, so don't add one if postgres can't make use of it!

I found an old thread that examines some of the early usage of deps. Data > macros does indeed seem to be a driving force: https://clojureverse.org/t/combining-tools-deps-with-leining...

tools.deps makes better choices when dependency specs conflict, so I would suggest trying https://github.com/RickMoynihan/lein-tools-deps if you otherwise want to use lein, and get the best of both worlds.

By better, I mean:

Leiningen and Maven, when there is a conflict always pick the version that is closest to the root of the dependency tree; where as tools.deps always picks the newest.

I've used native-image both directly and indirectly. Directly to implement a Clojure-language authentication server which needed a small memory footprint. Indirectly through @borkdude's https://github.com/babashka/babashka which provides a native-image binary that can run much of the Clojure language.

We open-sourced some babashka code at https://github.com/staticweb-io/staticweb-open-wp/tree/maste... One major caveat: when I wrote that code, babashka didn't have any MySQL support, so I shelled out to the MySQL CLI. Later, I figured out how to compile the MySQL JDBC drivers with native-image and it's now available at https://github.com/babashka/babashka-sql-pods along with HSQLDB, SQL Server, Oracle, and Postgres drivers.