Packages
ecto_hrana
0.1.0
Ecto adapter for libSQL servers (Turso, Bunny Database) over Hrana on HTTP
Current section
Files
Jump to
Current section
Files
ecto_hrana
README.md
README.md
# EctoHrana
Prototype of an Ecto adapter for libSQL servers (Turso, Bunny Database,
`sqld`), over the Hrana protocol on HTTP, in pure Elixir.
libSQL speaks SQLite's dialect, so the SQL generation, the migrations, the
loaders/dumpers and the constraint errors are `ecto_sqlite3`'s: only the driver
(`EctoHrana.Connection`) is new.
```elixir
defmodule MyApp.Repo do
use Ecto.Repo, otp_app: :my_app, adapter: Ecto.Adapters.Hrana
end
config :my_app, MyApp.Repo,
uri: "libsql://my-db.turso.io",
auth_token: System.fetch_env!("LIBSQL_AUTH_TOKEN")
```
## Motivations
- **Pure Elixir, no native code.** `ecto_libsql` wraps libSQL's Rust library
in a NIF: it needs a precompiled binary for the target (or a Rust
toolchain), and a crash in native code takes the whole VM down. Against a
remote server, the native library is not needed: Hrana is HTTP and JSON,
which `Req` and `Jason` speak. This adapter builds and runs wherever the
BEAM does, and a failing connection is an ordinary process crash, restarted
by `DBConnection`.
- **Reuse rather than rewrite.** libSQL speaks SQLite's dialect, and
`ecto_sqlite3` already generates it, runs the migrations, loads and dumps
the types and maps the constraint errors. Only the transport is new, so the
behaviour is the one SQLite users already know, `ash_sqlite` included.
- **Hosted libSQL, from Elixir.** Turso and Bunny Database expose libSQL over
Hrana: this lets an Ecto (or Ash) application use them like any other
database, with transactions and savepoints.
## Limitations
- A prototype: it passes its tests against `sqld` and a full Ash application
test suite, but has not been used against a remote server in production.
- Each statement is an HTTP round trip to the server: against a remote
server, the network latency dominates. Keep the application close to the
database and avoid N+1 queries.
- Streams are emulated: `Repo.stream/2` fetches all the rows at once.
- No embedded replicas (a local copy synchronised with the server), which
need libSQL's native library.
- The SQL generation comes from `ecto_sqlite3`'s internal modules, so the
`ecto_sqlite3` versions this library works with are pinned.
As with `ecto_sqlite3`, `query_many/4` is not supported: run the statements
one by one.
## Development
The tests and `bench/compare.exs` need a libSQL server:
docker run -p 127.0.0.1:8080:8080 ghcr.io/tursodatabase/libsql-server:latest
## License
MIT, see [LICENSE](LICENSE).