Documentation index

MyCount follows the shared data access structure used by R3el and Ax3l. Application operations belong in domain database interfaces, which use the generic mycount/interface/DbMgr.py bridge. That bridge owns the MariaDB connection, cursors, SQL execution, and transaction mechanics.

mycount/entity/Visit.py holds validated visit data during processing. It is an immutable dataclass with no database operations. Processing activities can return enriched copies using dataclasses.replace; validation belongs at the input boundary and persistence belongs in the database interface.

Connection and transactions

The Python code requires Python 3.11 or later and the dependencies declared in requirements.txt. DbMgr reads DB_HOST, DB_NAME, DB_USER, and DB_PASSWORD from the process environment. DB_PORT defaults to 3306. The installer stores credentials in /etc/mycount/database.env; the service launcher must supply them to the process. The database manager does not execute or load that file itself.

Each manager owns one connection and must be closed by its owner in a finally block. Workers must not share a connection across threads. Connections use UTF-8, UTC, and bounded connection and I/O timeouts.

execute, insert, and query accept SQL with bound parameters. Domain interfaces own application SQL and choose which operations must succeed together. Writes outside transaction() are autocommitted. A transaction commits on success and rolls back on failure; database exceptions propagate to the caller. transaction(read_only=True) supports read-only reporting. Transactions must not be nested, and schema operations must run separately.

Explicit schema setup

mycount/activity/VisitorSchema.py owns schema creation. Opening a connection does not create or change tables. With the database already provisioned and the credentials present in the environment, the schema entry point is:

python3 -B -m mycount.activity.VisitorSchema

The installer explicitly applies VisitorSchema and GeoIpSchema. Setup creates missing tables and preserves existing visitor records on repeated runs. Changes to existing tables use explicit migrations; rerunning CREATE TABLE IF NOT EXISTS does not alter them.

The schema provides relational constraints and reporting indexes. Its definition lives in the source code. GeoIP source access, reference-data refresh, lookups, and visit persistence each have a separate component using the shared database bridge. Fingerprint generation remains unfinished.

Focused checks

Run these from the checkout using a Python environment with requirements.txt installed:

python3 -B -m unittest discover -s tests -p 'test_db_mgr.py' -v
python3 -B -m unittest discover -s tests -p 'test_geoip.py' -v
PATH="/usr/sbin:$PATH" python3 -B -m unittest discover -s tests -p 'test_database.py' -v

The first two commands test database mechanics and CSV parsing locally. The last starts a disposable MariaDB instance under a temporary directory, tests the actual schema and transactions, and removes the instance afterward. It requires mariadb-install-db and mariadbd on PATH and permission to open a local listening socket. It does not use an existing database server. These checks do not invoke Git or release scripts.