Files
warmbly/cmd/sandbox/main.go
T

67 lines
1.9 KiB
Go

// Sandbox: a fully working local demo environment.
//
// Seeds a paid showcase org ("Sunrise Labs") whose mailboxes really send
// (SMTP -> mailpit) and really sync (IMAP <- dovecot), then runs a simulator
// that plays the internet: routing captured mail into recipient inboxes,
// opening tracking pixels, clicking tracked links, and replying as the seeded
// contacts. The platform side (scheduler, worker, consumer, tracking,
// realtime) is all production code; run it with `make infra` + `make run` +
// `make tracking` (+ `make realtime` + `make web` for the live dashboard).
//
// make sandbox # seed + simulate (foreground)
// go run ./cmd/sandbox -seed-only
// go run ./cmd/sandbox -simulate-only
//
// Documented at docs.warmbly.com/development/sandbox/.
package main
import (
"context"
"flag"
"log"
"os/signal"
"syscall"
"time"
"github.com/jackc/pgx/v5/pgxpool"
"github.com/warmbly/warmbly/internal/infrastructure/db"
"github.com/warmbly/warmbly/internal/sandbox"
)
func main() {
seedOnly := flag.Bool("seed-only", false, "seed the sandbox org and exit")
simulateOnly := flag.Bool("simulate-only", false, "skip seeding, run only the simulator")
flag.Parse()
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
cfg := sandbox.FromEnv()
pool, err := pgxpool.New(ctx, cfg.DatabaseURL)
if err != nil {
log.Fatalf("connect: %v", err)
}
defer pool.Close()
if !*simulateOnly {
// Migrations first so the sandbox works on a fresh database.
if err := db.RunMigrations(cfg.DatabaseURL); err != nil {
log.Fatalf("migrations: %v", err)
}
seedCtx, cancel := context.WithTimeout(ctx, 120*time.Second)
if err := sandbox.Seed(seedCtx, pool, cfg); err != nil {
cancel()
log.Fatalf("seed: %v", err)
}
cancel()
}
if *seedOnly {
return
}
if err := sandbox.Simulate(ctx, pool, cfg); err != nil {
log.Fatalf("simulate: %v", err)
}
}