Skip to content

Latest commit

 

History

History
101 lines (67 loc) · 5.99 KB

File metadata and controls

101 lines (67 loc) · 5.99 KB

Phoenix + Postgres + Meilisearch (Scrypath example)

Minimal API-only Phoenix app that depends on Scrypath via path: "../.." from the monorepo root. It shows the same patterns as the main README (searchable schema, Scrypath.sync_record/3, Scrypath.search/3 with repo:) against real Postgres and real Meilisearch, plus Oban wired for a second integration path (sync_mode: :oban) so the example matches queue-backed production apps. It also demonstrates the related-data fan-out path via Scrypath.sync_related/3, showing how an Author rename propagates to that author's Post search documents through both inline and Oban-backed fan-out modes.

This README is the proof/runbook surface for the real-service path. The HexDocs guides teach the public request-edge boundary and API shape; this example proves the operational path, CI parity, env vars, and local smoke commands.

From the repository root, the canonical maintainer entrypoint for this live path is mix verify.adopter --live. That root task checks for SCRYPATH_EXAMPLE_INTEGRATION, PGPORT, and SCRYPATH_MEILISEARCH_URL, verifies Postgres and Meilisearch are reachable, then shells into this example with cd examples/phoenix_meilisearch && mix deps.get && mix test (the same sequence CI uses).

Prerequisites

  • Elixir 1.17+ and Erlang/OTP as in the parent project
  • Docker with Compose v2

Stack (Docker)

compose.yaml starts:

  • Postgres 16 on host port 5433 (avoids colliding with a local Postgres on 5432). Override with PGPORT if you change the mapping.
  • Meilisearch v1.15 on host port 7700 (same image tag as library CI).

Both services attach to an explicit bridge network scrypath_phx_meili_net so you can add an app container later without reworking the layout.

docker compose up -d

Configure ports and flags (authoritative)

Variable Purpose Default
PGPORT Postgres TCP port on localhost 5433 (config/dev.exs, config/test.exs)
SCRYPATH_MEILISEARCH_URL Meilisearch base URL http://127.0.0.1:7700
SCRYPATH_EXAMPLE_INTEGRATION When 1 / true, ExUnit runs @moduletag :integration smoke tests (inline + Oban paths, including fan-out smokes) unset (those tests excluded)

CI uses the same Meilisearch v1.15 image tag as this compose.yaml (see root CONTRIBUTING.md for which GitHub Actions jobs run live Meilisearch). This README is the single detailed runbook for the example; the golden path links here instead of duplicating the table.

GitHub Actions (phoenix-example-integration)

On pull requests and pushes to main, job phoenix-example-integration starts Postgres 16 and Meilisearch v1.15 as workflow services, sets SCRYPATH_EXAMPLE_INTEGRATION=1, PGPORT=5433, and SCRYPATH_MEILISEARCH_URL=http://127.0.0.1:7700, then runs (from the repository root):

cd examples/phoenix_meilisearch
mix deps.get
mix test

CI uses that mix deps.get then mix test sequence as the test driver for this example. ./scripts/smoke.sh is local orchestration (Docker Compose + the same env defaults); it is not what GitHub Actions invokes in place of the mix steps above.

End-to-end smoke

From this directory (with Compose running or let the script start it):

./scripts/smoke.sh

CI-shaped default: the script always runs docker compose down on exit (trap), so machines do not leak containers—best for automation and first-time contributors.

Local iteration: pass --keep-up to skip teardown and reuse the same Postgres/Meilisearch while you edit tests (./scripts/smoke.sh --keep-up). When finished, run docker compose down from this directory.

The script:

  1. Runs docker compose up -d and fails fast if Postgres or Meilisearch is not healthy within 60s.
  2. Sets SCRYPATH_EXAMPLE_INTEGRATION=1 so ExUnit includes @moduletag :integration smoke tests.
  3. Runs mix deps.get and mix test (the test alias creates the test DB and migrates, including Oban migrations).

Integration coverage:

  • Inline — insert row, Scrypath.sync_record with sync_mode: :inline, then Scrypath.search with hydration via ScrypathDemo.Repo.
  • Oban — same shape with sync_mode: :oban and ScrypathDemo.Oban; tests use config :scrypath_demo, Oban, testing: :inline so jobs run in-process deterministically while still exercising enqueue metadata and Scrypath.Oban.UpsertWorker against live Meilisearch.
  • Fan-out Inline — insert Author + Post, rename the Author via ScrypathDemo.Blog.update_author/3 with sync_mode: :inline (exercises Scrypath.sync_related/3), then assert the Post search document reflects the new author_name. Verifies the inline resolver-arity path (resolver receives Author structs).
  • Fan-out Oban — same Author rename via update_author/3 with sync_mode: :oban, asserting {:ok, %{mode: :oban, status: :accepted}}. Under testing: :inline, the Scrypath.Sync.RelatedWorker runs in-process and await_search confirms the renamed author_name reaches the Post document. Verifies the oban resolver-arity path (resolver receives Author document IDs).

Tests without integration

With Compose Postgres still required (Sandbox + ConnCase):

docker compose up -d
export PGPORT=5433
mix deps.get
mix test

Integration tests are excluded unless SCRYPATH_EXAMPLE_INTEGRATION=1 (or true). That loop is what you want when iterating quickly without tearing Compose down each time (contrast with ./scripts/smoke.sh default, which always stops Compose on exit).

Development

docker compose up -d
export PGPORT=5433
mix deps.get
mix ecto.create
mix ecto.migrate
mix phx.server

Learn more