Skip to content

Dev#606

Merged
burakogut5 merged 8 commits into
mainfrom
dev
May 13, 2026
Merged

Dev#606
burakogut5 merged 8 commits into
mainfrom
dev

Conversation

@LifelongWay

Copy link
Copy Markdown
Contributor

No description provided.

mehmetborasarioglu and others added 8 commits May 13, 2026 12:02
Adds a self-contained pipeline that captures the current hand-crafted
demo state (78 users, 288 posts, 6 active + 48 past mentorships, 45
ratings, 100 messages, 389 binary uploads) into a portable snapshot
and replays it on a fresh DB without any HTTP/API calls.

- scripts/seed.sh: single bash entry point (setup/dump/load/status).
  Bootstraps a local .venv on first run, pre-flights docker, and
  dispatches to seed_snapshot.py.
- scripts/seed_snapshot.py: psycopg COPY + docker-cp based dump/load.
  Writes seed-owned rows in FK order, restores backend uploads tree.
  Idempotent — DELETE-then-COPY semantics on load.
- scripts/seed_snapshot_data/: committed snapshot artifact (~109 MB).
  Lets a fresh checkout reach demo state in ~1.5 seconds.
- scripts/seed_demo_*.py: the full Phase A-V builder that produced
  the snapshot, kept around for future regenerations. Phase A now
  auto-applies coordinates + backfills bio/goals/availability from
  the markdown corpus so the snapshot is reproducible end-to-end.
- docker-compose.yml: three new env defaults required by the seed
  flow (APP_RATELIMIT_ENABLED, FOLLOW_GRAPH_SYNC_ENABLED, FOLLOW_RANKER).
- .gitignore: ignore .venv/, .env.*, seed-pipeline runtime artifacts.

Fresh-machine flow:

    docker compose up -d
    ./scripts/seed.sh load
Add a docker-compose service that loads the snapshot into Postgres and
into the shared uploads volume when the stack is brought up with
`--profile demo`. Without the flag the service is dormant.

- docker-compose.yml: new `seed` service, profile-gated. Uses
  python:3.12-slim, depends on backend health, mounts the scripts/
  tree read-only plus the uploads_data volume, runs seed_snapshot.py
  in `--uploads-mode local` so it writes directly to the volume
  (no docker daemon access inside compose).
- scripts/seed_snapshot.py: support running inside compose. DSN now
  auto-detects POSTGRES_HOST (so the same script works from the host
  and from inside the `seed` service). New `--uploads-mode local`
  flag short-circuits the `docker cp` path and copies files with
  shutil instead.
- README.md: document the `--profile demo` flow plus the host-side
  `./scripts/seed.sh load` wrapper.

Fresh-machine deploy flow now compresses to:

    docker compose --profile demo up -d

…and the stack comes up already seeded with the hand-crafted demo
state. Without the profile, behaviour is unchanged: clean DB.
Without these flags the `--profile demo` stack boots, but the UI
quietly falls back to the legacy ranker, blank mentor explanations,
and a 401 on any registration attempt. Make the demo defaults explicit
and explain each knob.

- .env.example: pre-set every flag the demo dataset wants
  (APP_RATELIMIT_ENABLED=false, APP_EMAIL_ENABLED=false,
  APP_SPAM_ENABLED=false; MENTOR_ADVANCED_RANKER=true,
  MENTOR_EXPLANATION_ENABLED=true, MENTOR_EXPLANATION_TIMEOUT_MS=15000;
  FEED_ADVANCED_RANKER=true; FOLLOW_RANKER=advanced). The
  docker-compose `:-` fallbacks still ship prod-safe defaults, so
  forgetting to copy .env.example yields a prod-shaped boot.
- README.md: new "Environment variable reference" section with three
  tables — seed-friendliness, advanced ranker stack, and keys to set
  manually (chiefly OPENAI_API_KEY for LLM explanations + semantic
  affinity).

Re-runnable demo flow now matches the snapshot's intent end-to-end:

    cp .env.example .env
    docker compose --profile demo up -d
Two friction points uncovered while dry-running the README on a fresh
checkout:

1. Quick start and the seed section listed two different commands
   (`docker compose up --build` and `docker compose --profile demo up -d`).
   Collapse them into one canonical fresh-clone command:

       docker compose --profile demo up --build -d

   `--profile demo` enables the one-shot seed service; `--build` covers
   the first-run image build (backend, frontend, custom Neo4j-GDS).
   Omit the profile to get a clean DB instead.

2. `docker compose down` without `--profile demo` leaves the seed
   container orphaned with a stale network reference; the next `up`
   then fails with "network not found". Document explicitly that the
   teardown command must include the profile too, and surface the
   `run --rm seed` recipe for re-seeding against a running stack.

Also collapse the duplicated "Seed local data" block into a single
"Seeding options" section that points back at the Quick start for the
primary command and only lists the host-side wrapper / legacy seeder
as alternates.
The production droplet runs the same docker-compose.yml as local dev
(bundled Postgres + Neo4j, prod-grade .env), so the demo profile works
identically there. Wire it into the existing deploy workflow:

- .github/workflows/deploy.yml: add `--profile demo` to the compose
  invocation so the one-shot `seed` service runs after the backend
  reports healthy. Also pin command_timeout: 30m explicitly (it had
  rotted out of this branch but is needed for cold rebuilds), and
  add `set -e` so the workflow fails loudly if any step breaks.
- README.md: rewrite the Production deployment section to describe
  the actual deploy path (GitHub Actions → SSH → docker compose
  --profile demo up --build -d) and list the env flags the droplet
  needs to surface the full advanced-ranker UI. The standalone
  docker-compose.prod.yml flow stays documented as the hardened
  alternative.

The seed is idempotent and scoped to %@seed.test rows. Real users
registered through the UI on the live site are never touched.
The orphan-cleanup queries in AttachmentRepository previously checked
only `messages` and `feed_post_attachments`, but four tables hold a
foreign key to `attachments(id)`:

  - messages.attachment_id                  (V15, ON DELETE SET NULL)
  - feed_post_attachments.attachment_id     (V41, NO ACTION)
  - task_assignment_attachments.attachment_id  (V23, ON DELETE CASCADE)
  - task_submission_attachments.attachment_id  (V23, ON DELETE CASCADE)

Because the task-attachment junctions cascade on attachment delete,
the daily 03:15 UTC orphan sweep would silently drop task assignment
PDFs and task submission files older than the 24h retention window:

  1. `findOrphansOlderThan` returns the attachment row as a candidate
     (passes the messages/feed_post_attachments NOT EXISTS check).
  2. `deleteIfStillOrphan` deletes the attachment row.
  3. The CASCADE on `task_*_attachments.attachment_id` drops the
     junction row, removing the task's file reference entirely.
  4. Result: the file vanishes from the task detail view on both
     web and mobile, with no audit trail.

Add `NOT EXISTS` clauses for both task junctions to both queries, and
expand the javadoc to enumerate the canonical list of FK sources so
future schema additions stay in sync.

No migration is needed (the queries are in code, not in
flyway_schema_history). Existing orphan rows in production that have
already been swept are unrecoverable, but the seed snapshot
re-uploads its task PDFs on every deploy so the demo dataset
self-heals.
feat(scripts): reproducible demo seed via snapshot dump/load
@burakogut5 burakogut5 self-requested a review May 13, 2026 10:27

@burakogut5 burakogut5 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GREAT

@burakogut5 burakogut5 merged commit 498dde0 into main May 13, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants