Moe-Counter Compatible Website Hit Counter
Mayu is a drop-in replacement for Moe-Counter. It serves the same counter routes and reads Moe-Counter's existing SQLite database.
Mayu commits every hit to the database as it arrives, so a crashed or killed process loses no counts. On one CPU, Mayu served 4,165 SVG counters per second while saving every hit. Moe-Counter served 317 per second when it also saved every hit. With every theme loaded, an idle Mayu container uses 45 MiB of memory. An idle container from Moe-Counter's official image uses 90 MiB. Mayu's Docker image is 66 MB compressed, and Moe-Counter's is 84 MB.
Mayu is written in Gleam and stores counters in SQLite or PostgreSQL.
The theme query parameter of a get request selects the theme, for example
mayu.due.moe/get/@demo?theme=urushi.
This repository tracks four original themes: garukura, lain, urushi, and yuruyuri.
./scripts/sync-themes.sh adds the rest of the Moe-Counter
theme collection, including asoul, gelbooru, moebooru, and rule34. The Docker image runs
the script at build time; run it yourself after cloning to get the full set locally.
The script fetches the upstream revision pinned inside it and copies only files that are missing locally. It never replaces or deletes local files. To copy from a local upstream checkout instead, pass its path as the first argument.
Mayu pads the count with leading zeroes to 6 digits. The padding query parameter of a get
request changes this, up to a maximum of 12.
$ git clone git@github.com:Fuwn/mayu.git
$ cd mayu
$ gleam runWith Nix, nix develop provides the Gleam, Erlang, and rebar3 toolchain.
docker run --volume 'mayu:/mayu/data/' -p '80:3000' --rm fuwn/mayu:latestThe named volume, mayu, keeps the SQLite database across container restarts. PostgreSQL
deployments do not need it, because the data lives in the database server.
Mayu listens on port 3000 unless PORT is set, and binds every interface over both IPv4 and IPv6.
By default, Mayu stores counters in SQLite at data/count.db, relative to the working directory.
In the Docker image, that is /mayu/data/count.db.
To use PostgreSQL instead, set MAYU_DATABASE_URL to a postgres:// or postgresql:// URL, for
example postgres://mayu:secret@localhost:5432/mayu. Add ?sslmode=require if your provider
requires TLS. Mayu creates its table on start-up, so an empty database is enough.
Mayu uses Moe-Counter's table layout. To keep existing counts, copy Moe-Counter's database file to
data/count.db before starting Mayu.
On start-up, Mayu adds created_at and updated_at columns if the table lacks them. The record
route returns these timestamps; counters that existed before the columns were added report an empty
created_at.
Mayu reads its configuration from environment variables. All of them are optional.
| Variable | Description |
|---|---|
PORT |
Port the server listens on. Defaults to 3000. |
MAYU_DATABASE_URL |
A postgres:// or postgresql:// URL. When unset, Mayu uses the SQLite file at data/count.db. |
MAYU_THEMES |
Comma-separated list of themes to load, for example asoul,garukura. When unset, Mayu loads every theme. A shorter list uses less memory and lowers the largest possible response. |
MAYU_PRUNE_MIN_COUNT |
Counters with fewer than this many hits are eligible for pruning. |
MAYU_PRUNE_AFTER_DAYS |
Counters not incremented within this many days are eligible for pruning. |
MAYU_PRUNE_EVERY_HOURS |
How often, in hours, the prune sweep runs. |
Pruning runs only when all three MAYU_PRUNE_* variables are positive integers. Each sweep deletes
a counter only if it has fewer than MAYU_PRUNE_MIN_COUNT hits and no hits within
MAYU_PRUNE_AFTER_DAYS days. A counter that meets just one of those conditions stays.
/serves the homepage, which builds embed snippets for a counter./get/@nameincrements counternameand returns it as animage/svg+xmlimage. It accepts thethemeandpaddingquery parameters. Without a validtheme, Mayu usesasoulif it is loaded, otherwise the first loaded theme in alphabetical order whose name does not end in-h./record/@nameincrements counternameand returns itsname,num,created_at, andupdated_atas JSON./heart-beatreturnsalive.
Counter names must be 1 to 64 characters long. The demo counter always shows 1234567890 and is
never stored. Any other path redirects to this repository.
gleam test runs the SQLite and request tests.
MAYU_TEST_DATABASE_URL=postgres://postgres@localhost:5432/mayu_test gleam run -m postgres_test
runs the PostgreSQL tests. They work in a temporary schema inside a transaction, then roll the
transaction back so the database keeps its previous state.
python3 test/http_smoke.py http://localhost:3000 checks a running instance, including
concurrent increments. It creates a counter, so point it at a disposable database. CI runs it
against the built container.
- A-SOUL_Official
- Moebooru
- Rule 34 (NSFW)
- Gelbooru (NSFW)
- Urushi
- Lain Iwakura
- GaruKura
This project is licensed under the GNU General Public License v3.0.