mirror of
https://github.com/ArchiveBox/ArchiveBox.git
synced 2026-09-13 18:46:17 +05:00
Add DATABASE_ENGINE=postgres (plus DATABASE_HOST/PORT/USER/PASSWORD/NAME) config and centralize all sqlite-vs-postgres branching in archivebox.misc.db: - get_database_settings() builds DATABASES for either backend; the sqlite path is unchanged (custom lock-retry backend, same PRAGMAs). - database_exists()/ensure_database_ready() replace index.sqlite3 file checks; init auto-creates the postgres database when missing. - approximate_row_counts() serves admin index counts from sqlite_stat1 or pg_class.reltuples; missing-table detection covers both vendors. - rebuild_models_from_migration_state() lets historical sqlite-only raw SQL migrations resync postgres schema from Django migration state at every divergence point (postgres can never hold legacy data, so affected tables are empty when these run). All raw-DDL and PRAGMA migrations are now vendor-gated with sqlite behavior byte-for-byte unchanged. - A pre_save clamp truncates CharField values to max_length: sqlite never enforced varchar(n) but postgres does (e.g. long crawl labels). - Collation-sensitive URL range scans branch to escaped LIKE on postgres (with a text_pattern_ops index) since linguistic collations break bytewise range tricks; the crawl-config JSON search wave gets a jsonb-text implementation. Verified on real PostgreSQL 16: fresh init applies the entire migration graph, schema matches models exactly (column-level parity check + makemigrations --check), and add/run/list/search/status/remove all work end-to-end. New test_postgres_backend.py suite boots a real throwaway postgres cluster (initdb + pg_ctl); CI workflows install postgres server binaries. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YHSjZM6TstSAMN2PhgfUg
54 lines
2.0 KiB
Python
54 lines
2.0 KiB
Python
__package__ = "archivebox.core"
|
|
|
|
from django.apps import AppConfig
|
|
import os
|
|
|
|
|
|
class CoreConfig(AppConfig):
|
|
name = "archivebox.core"
|
|
label = "core"
|
|
|
|
def ready(self):
|
|
"""Register the archivebox.core.admin_site as the main django admin site"""
|
|
import sys
|
|
from django.utils.autoreload import DJANGO_AUTORELOAD_ENV
|
|
|
|
from archivebox.core.admin_site import register_admin_site
|
|
|
|
register_admin_site()
|
|
from archivebox.base_models.models import ModelWithOutputDir
|
|
|
|
ModelWithOutputDir.register_delete_signal()
|
|
|
|
# SQLite ignores VARCHAR(n) limits but PostgreSQL enforces them; clamp
|
|
# CharField values on save so writes behave the same on both backends.
|
|
from django.db.models.signals import pre_save
|
|
|
|
from archivebox.misc.db import truncate_overlong_charfields
|
|
|
|
pre_save.connect(truncate_overlong_charfields, dispatch_uid="archivebox_truncate_overlong_charfields")
|
|
|
|
# Import models to register state machines with the registry
|
|
# Skip during makemigrations to avoid premature state machine access
|
|
if "makemigrations" not in sys.argv:
|
|
from archivebox.core import models # noqa: F401
|
|
|
|
def _should_prepare_runtime() -> bool:
|
|
if os.environ.get("ARCHIVEBOX_RUNSERVER") == "1":
|
|
if os.environ.get("ARCHIVEBOX_AUTORELOAD") == "1":
|
|
return os.environ.get(DJANGO_AUTORELOAD_ENV) == "true"
|
|
return True
|
|
return False
|
|
|
|
if _should_prepare_runtime():
|
|
from archivebox.config import CONSTANTS
|
|
from archivebox.machine.models import Process
|
|
|
|
Process.current().mark_running(
|
|
process_type=Process.TypeChoices.WORKER,
|
|
worker_type="worker_runserver",
|
|
pwd=str(CONSTANTS.DATA_DIR),
|
|
url=os.environ.get("ARCHIVEBOX_RUNSERVER_BIND_URL") or "",
|
|
timeout=CONSTANTS.MAX_HOOK_RUNTIME_SECONDS,
|
|
)
|