Skip to content

Commit 27c0264

Browse files
committed
docs(periodic_scheduler): add LLM agent onboarding references
1 parent 40f7711 commit 27c0264

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Repository Guidelines
2+
3+
## Project Structure & Module Organization
4+
Runtime code lives under `lib/`, split by domain boundaries (`scheduler/`, `actions/`, `workers/`). Persistence details sit in `lib/scheduler/periodics` and `lib/scheduler/front_db` with schemas mirroring tables. Configuration defaults are in `config/config.exs`, with environment overrides in `config/{dev,test,prod}.exs`. Database migrations and seeds are under `priv/{periodics_repo,front_repo}/`, while `test/` mirrors `lib/` one-to-one for ExUnit coverage. Docker, release, and deployment assets reside in `docker-compose.yml`, `rel/`, and `helm/`. Shared automation scripts sit inside `scripts/`. For a deeper walkthrough, treat `DOCUMENTATION.md` as the go-to triage guide before diving into tasks.
5+
6+
## Build, Test, and Development Commands
7+
- `mix deps.get && mix compile` installs dependencies and compiles the application locally.
8+
- `MIX_ENV=test make test.ex.setup` prepares the Postgres schema inside Docker for integration tests.
9+
- `mix test` or `mix test --cover` runs the ExUnit suite (JUnit formatter available via `MIX_ENV=test mix test --formatter JUnitFormatter` for CI).
10+
- `mix credo --strict` runs linting, and `mix format` enforces the formatter prior to commits.
11+
- `docker compose up app` boots the scheduler in a container with RabbitMQ/Postgres defaults from the `.env` files.
12+
13+
## Coding Style & Naming Conventions
14+
Follow the default Elixir formatter (2-space indentation, pipe-first style). Modules use `Scheduler.*` namespaces that map to folders (e.g., `Scheduler.Periodic.Job``lib/scheduler/periodic/job.ex`). Functions are snake_case verbs, macros are camel-case nouns, and tests end in `_test.exs`. Keep public modules documented with `@moduledoc` and prefer pattern matching + guard clauses over nested conditionals. Run `mix format && mix credo` before every push.
15+
16+
## Testing Guidelines
17+
Author unit tests alongside code in `test/<mirror_path>_test.exs`. Use ExUnit’s `describe` blocks per function and tag integration tests with `@moduletag :integration` so CI can filter. Ensure new DB queries include data factories from `test/support`. Aim to maintain or improve coverage reported by `mix test --cover`; add regression tests for every bugfix.
18+
19+
## Commit & Pull Request Guidelines
20+
Commits typically follow `type(scope): imperative summary (#issue)` as seen in `git log` (e.g., `fix(secrethub): align cache headers (#705)`). Keep commits focused and reference Jira/GitHub IDs in the summary. Pull requests must describe motivation, list test evidence (`mix test`, manual steps), and link related issues or design docs. Include screenshots or logs when UI/API behavior changes and request reviews from domain owners noted in CODEOWNERS.
21+
22+
## Security & Configuration Tips
23+
Never commit `.env` files or credentials; rely on the provided Docker defaults and override locally via `config/dev.secret.exs`. When touching `scripts/internal_protos.sh` or `pb.gen`, confirm you have VPN + GitHub access before cloning `renderedtext/internal_api`. Validate all scheduler configuration changes against `config/runtime.exs` to avoid breaking production start-up.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Repository Architecture Notes
2+
3+
## Purpose & High-Level Flow
4+
- This Mix project (`mix.exs`) hosts Semaphore’s periodic workflow scheduler. It exposes a gRPC API (`lib/scheduler/grpc_server.ex`, `lib/scheduler/health_check_server.ex`) that the control plane uses to CRUD periodic definitions and trigger runs.
5+
- `Scheduler.Application` boots the critical OTP tree: both Postgres repos, the gRPC servers, Quantum-based cron scheduler, the dynamic schedule task supervisor, initializer, and the RabbitMQ consumers that react to org block/unblock events.
6+
- At runtime, `Scheduler.Workers.QuantumScheduler` converts cron strings into Quantum jobs that call `Scheduler.Actions.start_schedule_task/2`. Each run spawns a `Scheduler.Workers.ScheduleTask` process to orchestrate workflow execution via downstream APIs.
7+
8+
## Directory Cheat Sheet
9+
- `lib/scheduler/*` holds service code grouped by concern (actions, workers, clients, repos, DB models, utils).
10+
- `lib/internal_api` mirrors protobuf/gRPC stubs pulled from `renderedtext/internal_api`. Run `make pb.gen` if proto inputs change.
11+
- `priv/periodics_repo` and `priv/front_repo` store migrations for the two databases. `lib/scheduler/periodics` and `lib/scheduler/front_db` carry the matching schemas/query modules.
12+
- `test/` mirrors `lib/` one-to-one; heavier integration helpers sit under `test/support`.
13+
- Deploy tooling: `Dockerfile`, `docker-compose.yml`, `helm/`, `rel/`. Helper scripts live in `scripts/` (notably `internal_protos.sh` and `vagrant_sudo`).
14+
15+
## Runtime Components
16+
- **Actions layer** (`lib/scheduler/actions*.ex`): thin service layer invoked by gRPC endpoints. Each action module (ApplyImpl, ListImpl, PersistImpl, etc.) encapsulates validation, DB access, and calls to external services. Metrics are emitted via Watchman (see counters in `Scheduler.Actions`).
17+
- **Workers**: `Initializer` pre-warms Quantum jobs by paging through `Scheduler.Periodics.Model.PeriodicsQueries`. `QuantumScheduler` owns long-lived cron jobs, while `ScheduleTaskManager` supervises short-lived `ScheduleTask` processes that call downstream APIs (`WorkflowClient`, `ProjecthubClient`, `RepositoryClient`, `RepoProxyClient`).
18+
- **Messaging**: `Scheduler.EventsConsumers.OrgBlocked` / `OrgUnblocked` subscribe to RabbitMQ via Tackle. They suspend/resume Quantum jobs in batches per organization.
19+
- **Feature flags & metrics**: `FeatureProvider.init/1` picks either YAML-based flags (when `FEATURE_YAML_PATH` exists) or the gRPC-driven `Scheduler.FeatureHubProvider`. Observability is wired through `watchman` and `vmstats` (`Scheduler.VmstatsSink`, `config/config.exs`).
20+
21+
## Data & Persistence
22+
- `Scheduler.PeriodicsRepo` targets the `periodics_*` database (cron definitions, triggers, delete requests). Key schemas live under `lib/scheduler/periodics/model/`.
23+
- `Scheduler.FrontRepo` connects to the `front_*` DB for project/org metadata (`lib/scheduler/front_db/*`).
24+
- Trigger history is modeled in `lib/scheduler/periodics_triggers/model`, offering both offset (`Scrivener`) and keyset (`Paginator`) pagination helpers.
25+
- Soft-delete pipeline: requests are staged through `lib/scheduler/delete_requests/model` and eventually cleared by workers.
26+
- Config lives in `config/*.exs` with prod overrides in `config/runtime.exs`; most secrets arrive via env vars (`DB_*`, `RABBITMQ_URL`, `INTERNAL_API_URL_*`).
27+
28+
## Build, Test, and Common Commands
29+
- `mix deps.get && mix compile` – install deps and compile locally.
30+
- `mix test` (optionally `--cover` or `--only integration`) – ExUnit suite; reports land in `./out/test-reports.xml` when `JunitFormatter` is enabled.
31+
- `MIX_ENV=test make test.ex.setup` – boot Postgres (docker compose) and run migrations + seeds for integration specs.
32+
- `mix credo --strict` and `mix format` – lint/format gates prior to commits.
33+
- `docker compose up app` – run the scheduler plus backing services via the provided compose file; adjust `.env` as needed.
34+
- `make pb.gen` – clone `renderedtext/internal_api`, regenerate protobuf stubs into `lib/internal_api`.
35+
36+
## External Dependencies & Touchpoints
37+
- gRPC backends: feature API, repository hub, repo proxy, project hub, and workflow API. Their endpoints are injected via `INTERNAL_API_URL_*` variables (see `config/runtime.exs`).
38+
- RabbitMQ exchange `organization_exchange` (routing keys `blocked` / `unblocked`) throttles scheduling when an org’s billing status changes.
39+
- FeatureProvider cache uses Cachex (started in `Scheduler.Application` for non-Test environments) with 10-minute TTL.
40+
- Metrics flow to Watchman/StatsD (namespaced by `METRICS_*` env vars); VM stats are emitted every 10s.
41+
42+
## Tips for Future Changes
43+
- Touching cron semantics? Update both Quantum job creation (`QuantumScheduler`) and the validation logic inside `Scheduler.Actions.ApplyImpl` / `PersistImpl`.
44+
- When adjusting DB queries, remember both pagination strategies (`paginate_offset` and `paginate_keyset`) and the mirrored tests in `test/periodics_*`.
45+
- New gRPC fields require regenerating protos (`make pb.gen`) and updating the transformation helpers in `Scheduler.Grpc.Server`.
46+
- Long-running tasks should go through `ScheduleTaskManager` to benefit from supervision and Watchman metrics; avoid blocking the Quantum scheduler process.

0 commit comments

Comments
 (0)