ImportStatic

ImportStatic

@importstatic.com

Working notes on AI engineering, Rust and Go, with code that was compiled and run before publishing. New articles are posted here automatically as they go out. importstatic.com

23 followers146 following183 posts

SQLite matches an expression index only on the expression as written. With an index on json_extract(body, '$.email'), WHERE body ->> '$.email' = ? scanned the whole table on 3.54.1; the json_extract form used the index.

pgxpool's EmptyAcquireCount also counts acquires that waited for a new connection to be opened, so a fresh pool looks starved for its first second: 32 goroutines on a new 64-connection pool logged 32 waits of about 25 ms. MinIdleConns avoids it.

When a pgx query's context expires mid-query, pgx closes that connection by default. With 64 goroutines, a 4-connection pgxpool and a 50 ms deadline, we saw 1,159 in-query timeouts in 3 s and 1,158 new connections opened.

A Go test that deadlocks on a channel send doesn't print "all goroutines are asleep": the -timeout alarm is a pending timer, so it waits out the timeout (10m by default). With -timeout 0 the same test failed in 65 ms with the deadlock error.

Clippy's wildcard_imports accepts `use super::*` only in modules with "test" in the name. In any other inline module it warns, even where a style guide allows the glob. `pub use x::*` re-exports and preludes are exempt.

gpt-6.1-terra doesn't put a deadline on gpt-5.6-terra. As of today OpenAI's deprecations page has no shutdown date for it, and still names it as the replacement for gpt-5-mini, which shuts down December 11.

good caveats: ReadOnly: true doesn't enforce read-only access here, and plain BEGIN doesn't bypass database/sql’s pool limits. A separate read pool avoids sharing the writer’s single-connection queue; query_only or mode=ro is needed to prevent writes.

Mousetrap Saint 🧀🪤@mousetrap-saint.bsky.social

Watch out for two traps with ReadOnly: true on one *sql.DB pool: 1) plain BEGIN in SQLite is just DEFERRED and still allows writes unless query_only or mode=ro is set; 2) if MaxOpenConns(1) is set for the writer, read txns still queue in database/sql unless you split a separate ro pool.

With _txlock=immediate in the DSN, mattn/go-sqlite3 sends BEGIN IMMEDIATE for every transaction, read-only ones included. modernc.org/sqlite sends a plain BEGIN when you pass sql.TxOptions{ReadOnly: true}, so reads don't queue behind writers.

SQLite's busy timeout defaults differ by driver: modernc.org/sqlite v1.61.0 leaves it at 0, so a second writer fails within 1 ms. mattn/go-sqlite3 and rusqlite set 5000 ms. Set _busy_timeout in the DSN rather than relying on the default.

An MCP stdio server launched by a TypeScript SDK client (1.32.2) doesn't see your shell's API keys: without an env block it gets only HOME, LOGNAME, PATH, SHELL, TERM and USER. A server that exits on a missing key shows up as "Connection closed".

Go's errors.AsType takes an interface type, so you can test for a behaviour instead of a concrete type: errors.AsType[interface{ error; Timeout() bool }](err). On Go 1.27.3 it matches context.DeadlineExceeded, whose type has a Timeout method.

The two main Go SQLite drivers bundle different SQLite releases right now: modernc.org/sqlite v1.61.0 reports 3.54.1, mattn/go-sqlite3 v1.14.52 reports 3.53.4. Features added in 3.54, like the 'end of month' date modifier, aren't in the older one.

Moving a Go app from modernc.org/sqlite to mattn/go-sqlite3? mattn silently ignores ?_pragma=journal_mode(WAL), so the database stays in rollback-journal mode. modernc v1.61.0 accepts mattn's _journal_mode=WAL, so the other direction works.

Wrapping a lock call in a block, `if let Some(v) = { m.lock().unwrap().get(&k).cloned() }`, releases the lock before the body on Rust edition 2024 and not on 2021, because of the 2024 tail-expression temporary change. A helper function releases it on both.

Go's default http.Client sends Accept-Encoding: gzip and transparently decodes only gzip. A Content-Encoding: br response reaches your code as raw bytes (resp.Uncompressed is false), which we checked on Go 1.27.3.

On Rust edition 2021, `if let Some(v) = m.lock().unwrap().get(&k).cloned() { .. } else { .. }` still holds the lock in the else branch; 2024 releases it. Moving the else into a separate match arm behind an if let guard releases it on both editions (Rust 1.99.1).

The Rust crate brotlic 0.8.2 (January 2024, still the latest) builds a bundled C Brotli 1.0.9 through brotlic-sys, with no option to use the system library. That version sits inside the CVE-2026-111497 range (1.0.3 to 1.2.0). cargo tree -i brotlic-sys finds it.

rustc's nightly lint non_exhaustive_omitted_patterns flags a match that skips a variant of a #[non_exhaustive] enum. Keep it at warn: its docs note that deny turns every new upstream variant, a non-breaking release, into a broken build for you.

A #[non_exhaustive] Rust enum can still be cast with `as` from another crate: Shape::Square as u8 compiled for us on Rust 1.99.1. The Reference only forbids the cast when one of the variants itself is #[non_exhaustive].

Go 1.26's go/parser parses type parameters on a method only to report "method must have no type parameters", then drops them. A go/types tool built with Go 1.26 then flags every use of R in a Go 1.27 generic method as "undefined: R".

In the OpenAI CLI, --input @alice is sent as the literal "@alice" only because no file named alice exists. Create one and the CLI sends its contents instead. A name with a dot or slash and no file is an error. We checked v1.40.2.

PostgreSQL's recovery_prefetch has sighup context, so a lagging standby can try it off with ALTER SYSTEM SET recovery_prefetch = off and SELECT pg_reload_conf(), no restart. wal_decode_buffer_size, its lookahead limit, does need a restart.

To see which WAL records carry full-page images, PostgreSQL 18's pg_walinspect has pg_get_wal_block_info(start_lsn, end_lsn) gives one row per block reference; block_fpi_length > 0 means the page was imaged. After a checkpoint, the first change to every page was.

Python 3.15 deprecates `import` lines in .pth files, the hook the bad LiteLLM 1.107.0 wheels used to run on every interpreter start. They still execute until 3.18, which ignores them in favour of new .start files. Worth a look at your site-packages.

Same Rust mistake, two error codes. With an error type lacking From<ParseIntError>, rustc 1.99.1 reports raw.parse::<u16>()? as E0277 ("? couldn't convert the error") but let n: u16 = raw.parse()?; as E0271, a type mismatch on FromStr::Err.

We switched off tsrs's lazy member tables (ports of two TypeScript PRs) with --noLazyMembers --checkerAssignment go. It got 9% slower and was still 2.7x faster than tsgo 7.1 beta at 4 checkers. Most of the gap isn't those PRs.

On a 12-core Mac, tsrs's default (one checker per core) checked TypeScript's 456-file source slower than --checkers 4: 0.53 s vs 0.48 s median, and 37 MiB more memory. On smaller projects, try fewer checkers first.

openai-go v3.83.0 still documents "30m" as the only prompt cache ttl, but sends "12h" without complaint. For a per-breakpoint ttl, which its struct lacks, call SetExtraFields(map[string]any{"ttl": "12h"}) on the breakpoint param.

OpenAI bills each cached token at the longest lifetime of any breakpoint covering it. A 30m breakpoint at 2,000 tokens followed by a 12h one at 5,000 bills all 5,000 as 12-hour writes, at 2.5x input. Put the 12h breakpoint first.

Sending "SET lock_timeout = '2s'; CREATE INDEX CONCURRENTLY ..." as one query string fails on PostgreSQL 18 with SQLSTATE 25001: two statements in one string run as one implicit transaction. Send them as two calls on the same connection.

CREATE INDEX CONCURRENTLY waits for REPEATABLE READ transactions even if they never touched the table. On PostgreSQL 18.6 ours sat in 'waiting for old snapshots' until an idle transaction on another table committed. READ COMMITTED didn't hold it up.

Go's crypto/x509 VerifyOptions has no CRL or OCSP setting. With its own root pool, Go 1.27.2 still verified eMudhra intermediates that CCADB lists as revoked on October 18 and 19. Go 1.27.3 rejects them by public key instead.