Skip to main content

H2HDB

Description

The H2HDB is a comprehensive database for organising and managing H@H comic collections. It offers a streamlined way to catalogue your comics, providing key information such as GID (Gallery ID), title, tags and more, ensuring your collection is always organised and accessible.


Features

  • Add new galleries to the database
  • Comporess H@H's galleries to a folder
  • Record the removed GIDs in a separate list
  • Coordinate bounded downloader and database-ingest turns
  • Write document (need?)

Installation and Usage

  1. Install uv. It manages the Python version and dependencies for you.

  2. Install the required packages.

    uv pip install h2hdb
    
  3. Run the script.

    uv run python -m h2hdb --config [json-path]
    

Config

{
    "h2h": {
        "download_path": "download",
        "cbz_max_size": 768,
        "cbz_grouping": "flat",
        "cbz_sort": "no"
    },
    "database": {
        "sql_type": "mariadb",
        "host": "localhost",
        "port": 3306,
        "user": "root",
        "password": "password",
        "database": "h2h"
    },
    "maintenance": {
        "optimize_enabled": true,
        "min_interval_seconds": 604800,
        "min_work_units": 1000,
        "min_data_free_bytes": 268435456,
        "min_data_free_ratio": 0.2,
        "lock_wait_seconds": 300
    },
    "logger": {
        "level": "INFO"
    }
}
  • h2h.download_path: H@H download path. The default is download.
  • h2h.cbz_path: directory for CBZ output. Unset (the default) disables CBZ output entirely; if given, it must be a non-empty path ("" is rejected).
  • h2h.cbz_max_size: maximum image size. The default is 768.
  • h2h.cbz_grouping: flat, date-yyyy, date-yyyy-mm, or date-yyyy-mm-dd. The default is flat.
  • h2h.cbz_sort: no, upload_time, download_time, gid, title, pages, or pages+[num]. The default is no.
  • h2h.file_hash_workers: maximum number of files read and hashed concurrently. The default is the smaller of 4 and the available CPU count; set it to 1 for serial hashing. Valid values are 132.
  • database.sql_type: mariadb or sqlite. The default is mariadb. Existing config files that still use mysql must update this field.
  • database.host, database.port, database.user, and database.password are only used for mariadb.
  • database.database: for mariadb, this is the database name. For sqlite, this is the path to the database file.
  • maintenance.optimize_enabled: enables automatic optimization in the resident main loop. Manual H2HDB.optimize_database() calls remain unconditional.
  • maintenance.min_interval_seconds: minimum time between automatic optimization evaluations. The default is seven days (604800).
  • maintenance.min_work_units: changed or removed galleries accumulated before an evaluation. New galleries do not count. The default is 1000.
  • maintenance.min_data_free_bytes and maintenance.min_data_free_ratio: minimum reclaimable space a table (or the SQLite database) must satisfy. Both thresholds must pass; the defaults are 256 MiB and 20%.
  • maintenance.lock_wait_seconds: one wait interval for the MariaDB cross-process database gate. The default is 300 seconds. A timeout is logged and retried rather than terminating the caller.
  • logger.level: one of NOTSET, DEBUG, INFO, WARNING, ERROR, or CRITICAL.

The main entry point remains resident and keeps its 30-minute periodic scan deadline, but it now polls the durable gallery_ingest_state every five seconds while waiting. A live downloader lease defers that scan; otherwise an ingest request wakes h2hdb without waiting for the old uninterruptible 30-minute sleep.

The singleton coordination row moves through INGEST_REQUESTED → INGESTING → READY → DOWNLOADING. A newly added row starts at INGEST_REQUESTED, so an upgraded or new installation completes one baseline scan before a downloader can claim READY. Downloader integrations use these public methods:

  • claim_download_turn(lease_seconds=...) returns a generation-fenced DownloadTurn, or None while h2hdb owns the turn.
  • renew_download_turn(turn, lease_seconds=...) extends a live downloader lease and returns whether that token still owns the generation.
  • request_gallery_ingest(turn) idempotently hands the generation to h2hdb.
  • finish_download_turn(turn, request) atomically hands off a successful root traversal and conditionally deletes only that request token.
  • get_gallery_ingest_state() exposes the durable phase and completed_generation; a downloader may start its next root request only after completed_generation >= turn.generation.

A fresh DOWNLOADING lease prevents h2hdb from starting a scan until the downloader requests handoff; a periodic deadline does not override it. If the downloader terminates, h2hdb takes over after the lease expires and ingests any complete gallery folders already published. An ingest acknowledgement is written only after repeated synchronize_once() calls converge to a pass with no new or changed galleries and scheduled maintenance succeeds. A background heartbeat renews the ingest lease throughout synchronization and MariaDB maintenance. SQLite lock contention is retried only within the current lease; before SQLite maintenance h2hdb renews once and stops the heartbeat so VACUUM's exclusive lock can fence competing coordination writers. A successful SQLite optimization can acknowledge after the timestamp expires only if its generation and owner token are still current. Another resident treats SQLite lock contention while claiming as temporarily unavailable and keeps polling. Owner tokens fence stale downloader and h2hdb processes from renewing or completing a newer turn. Persisted handoff provenance distinguishes an explicit live-token handoff from an expired downloader lease recovered by h2hdb, so a recovered stale token cannot later report success.

One download turn covers one root todownload_gids request and its complete deep traversal. A failed, cancelled, or interrupted traversal leaves that durable request in the queue and may use request_gallery_ingest() to hand off any complete files. A successful traversal uses finish_download_turn() so handoff and exact-token deletion share one transaction. If the same GID was already re-enqueued with a newer request token, deletion is a no-op: the completed live turn still hands off immediately and the newer request remains queued.

Completed removal and changed-gallery batches add work to the singleton database_maintenance_state row. Automatic optimization is evaluated only after both the work and time thresholds pass, and MariaDB runs OPTIMIZE TABLE only for base tables that also pass both reclaimable-space thresholds. h2hdb clients can wrap short database work in H2HDB.database_gate() so it waits while maintenance owns the same MariaDB named lock.

H2HDB records a source-filename manifest for each gallery. Adding, deleting, or renaming a source file marks that gallery's CBZ for rebuilding. This pending state remains in the database if CBZ output is disabled or a run is interrupted. During ingestion, the provisional pass creates only missing CBZ files for new galleries and preserves existing CBZ files. After all galleries have been processed, one final pass uses the stable exclusion set to perform any required rebuilds. Created CBZ files carry a small input-layout marker in their ZIP comment, allowing the final pass to detect normalized renames and filename swaps even after the database has been deleted and rebuilt. H2HDB does not hash or scrub CBZ file contents.


Q & A

  • Why are some images missing from the CBZ-files?

H2HDB does not compress images that are considered spam according to certain rules. If you encounter any images that you believe should have been included, please report the issue.

  • Why are some images in some CBZ files and not in other CBZ-files?

H2HDB learns the spam rule from the previous CBZ files. If you kill the CBZ files containing these images, the new CBZ files will not contain these images.


Credits

The project was created by Kuan-Lun Wang.


License

This project is distributed under the terms of the GNU General Public Licence (GPL). For detailed licence terms, see the LICENSE file included in this distribution.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

h2hdb-0.17.0.0.tar.gz (125.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

h2hdb-0.17.0.0-py3-none-any.whl (94.1 kB view details)

Uploaded Python 3

File details

Details for the file h2hdb-0.17.0.0.tar.gz.

File metadata

  • Download URL: h2hdb-0.17.0.0.tar.gz
  • Upload date:
  • Size: 125.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for h2hdb-0.17.0.0.tar.gz
Algorithm Hash digest
SHA256 daa2743930cbc799aa17a1bd0e9e810e39e6e14f25e787c93b90caf5050d0347
MD5 f652a04e0e4616c94d36d99370e4570e
BLAKE2b-256 863ca2f87d187616a979bec6eff94b7ea584d173c6a40818162f8f17055ef037

See more details on using hashes here.

Provenance

The following attestation bundles were made for h2hdb-0.17.0.0.tar.gz:

Publisher: publish.yml on Kuan-Lun/h2hdb

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file h2hdb-0.17.0.0-py3-none-any.whl.

File metadata

  • Download URL: h2hdb-0.17.0.0-py3-none-any.whl
  • Upload date:
  • Size: 94.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for h2hdb-0.17.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 24147b05b56962a7094556a2ea448d1952f17b9ca83eef90223faf449b934144
MD5 1963f67c4fffbd066d6916fb20ff827a
BLAKE2b-256 572ca6622f9a844e39c708073bbbcee57f0274fa2f93fb5da1974c152c02ec00

See more details on using hashes here.

Provenance

The following attestation bundles were made for h2hdb-0.17.0.0-py3-none-any.whl:

Publisher: publish.yml on Kuan-Lun/h2hdb

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.31.0

2 files

0.29.0

2 files

0.28.3

2 files

0.28.2

2 files

0.28.1

2 files

0.27.0

2 files

0.26.0

2 files

0.25.0

2 files

0.24.0

2 files

0.23.1

2 files

0.23.0.11

2 files

0.23.0.10

2 files

0.23.0.9

2 files

0.23.0.8

2 files

0.23.0.7

2 files

0.23.0.6

2 files

0.23.0.5

2 files

0.23.0.4

2 files

0.23.0.3

2 files

0.23.0.2

2 files

0.23.0.1

2 files

0.22.0.2

2 files

0.22.0.1

2 files

0.21.0.1

2 files

0.21.0.0

2 files

0.20.0.2

2 files

0.20.0.1

2 files

0.20.0.0

2 files

0.19.0.0

2 files

0.18.0.0

2 files

This release

0.17.0.0 This release

2 files

0.16.0.0

2 files

0.15.0.0

2 files

0.14.0.2

2 files

0.14.0.1

2 files

0.14.0.0

2 files

0.13.0.2

2 files

0.13.0.1

2 files

0.13.0.0

2 files

0.12.0.6

2 files

0.12.0.5

2 files

0.12.0.4

2 files

0.12.0.3

2 files

0.12.0.2

2 files

0.12.0.1

2 files

0.12.0.0

2 files

0.11.0.5

2 files

0.11.0.4

2 files

0.11.0.3

2 files

0.11.0.2

2 files

0.11.0.1

2 files

0.11.0.0

2 files

0.10.8.4

2 files

0.10.8.3

2 files

0.10.8.2

2 files

0.10.8.1

2 files

0.10.8.0

2 files

0.10.7.5

2 files

0.10.7.4

2 files

0.10.7.3

2 files

0.10.7.2

2 files

0.10.7.1

2 files

0.10.7.0

2 files

0.10.6.0

2 files

0.10.5.8

2 files

0.10.5.7

2 files

0.10.5.6

2 files

0.10.5.5

2 files

0.10.5.4

2 files

0.10.5.3

2 files

0.10.5.2

2 files

0.10.5.1

2 files

0.10.5.0

2 files

0.10.4.2

2 files

0.10.4.1

2 files

0.10.4.0

2 files

0.10.3.0

2 files

0.10.2.0

2 files

0.10.1.1

2 files

0.10.0.0

2 files

0.9.1.9

2 files

0.9.1.8

2 files

0.9.1.7

2 files

0.9.1.6

2 files

0.9.1.5

2 files

0.9.1.4

2 files

0.9.1.3

2 files

0.9.1.2

2 files

0.9.1.1

2 files

0.9.1.0

2 files

0.9.0.5

2 files

0.9.0.4

2 files

0.9.0.3

2 files

0.9.0.2

2 files

0.9.0.1

2 files

0.9.0.0

2 files

0.8.0.2

2 files

0.8.0.1

2 files

0.8.0.0

2 files

0.7.0.9

2 files

0.7.0.8

2 files

0.7.0.5

2 files

0.7.0.4

2 files

0.7.0.3

2 files

0.7.0.2

2 files

0.7.0.1

2 files

0.7.0.0

2 files

0.6.68.63

2 files

0.6.68.62

2 files

0.6.68.61

2 files

0.6.68.60

2 files

0.6.68.59

2 files

0.6.68.58

2 files

0.6.68.57

2 files

0.6.68.56

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page