需求描述:发布屏在员工叫号后播放语音;同场次手机号被叫号后可重新取号;登录连续失败限制调整为10次。 实现思路:发布屏按新批次去重触发中文语音;重复手机号仅拦截WAITING号码;登录限流使用10次阈值,并补充前后端回归测试与接口说明。
Queue API
Go 1.26 modular-monolith API for the scenic queue system. It uses the standard library HTTP router, GORM, PostgreSQL, versioned embedded SQL migrations and database-backed sessions.
Local run
-
Start PostgreSQL and create the database in
DATABASE_URL. -
Copy
.env.exampleto.env, replace both cryptographic keys, and export the variables. Keys must decode to exactly 32 random bytes. -
Run
go run ./cmd/api. WithMIGRATE_ON_START=true, embedded migrations run under a PostgreSQL advisory lock. -
Seed the local demo users, projects, queues, batches, devices and audit data with:
ADMIN_PASSWORD='replace-me' go run ./cmd/seedThe command is repeatable and prints the demo display and visitor paths. It resets only the
DEMO,RAFTandCABLEprojects. Default users are the protectedxqkwljtadminaccount andstaff; override the staff credential and primary-project values withADMIN_USERNAME,STAFF_USERNAME,ADMIN_PASSWORD,PROJECT_CODEandPROJECT_NAME.
For a production release, run go run ./cmd/migrate as a separate release Job
with MIGRATE_ON_START=false, then rotate the protected administrator password
with SUPER_ADMIN_PASSWORD='...' go run ./cmd/bootstrap-admin. Do not run the
seed command against production.
POST /api/staff/projects/{id}/tickets and
POST /api/staff/projects/{id}/call-next require an Idempotency-Key header.
Ticket creation requires an immutable integer party_size inside the project's
configured min_party_size / max_party_size range. A call-next request uses
{ "expected_revision": 12, "mode": "TICKET|PEOPLE", "count": 5 }.
TICKET selects up to count consecutive FIFO tickets. PEOPLE selects the
longest consecutive FIFO prefix whose total party size does not exceed count;
it never splits or skips a ticket and rejects when the first ticket alone is
larger than the requested target. Each mode has a separate project-level
anti-mistouch maximum.
If a phone already has waiting tickets in the current queue session, ticket creation returns
DUPLICATE_PHONE; repeat with the same request body except
allow_duplicate: true and a new idempotency key after the employee confirms.
Once the earlier ticket has been called, the same phone can take a new ticket
without duplicate confirmation.
GET /api/public/projects returns projects currently open for visitor
self-service, including each project's allowed party-size range.
POST /api/public/projects/{id}/tickets uses the same ticket
validation, queue locking and idempotency rules as the staff ticket flow, but
returns only the public ticket projection and a private status token. Public
ticket creation is rate-limited and audited as PUBLIC_TICKET_CREATED.
POST /api/public/status/search is a temporary non-production operational-test
endpoint. It accepts { "phone": "..." } and returns all current active
tickets associated with that phone. It is disabled when APP_ENV=production;
replace it with OTP or an external identity interface before formal launch.
POST /api/internal/status/search exposes the same active-ticket lookup to
trusted backend services in every environment. It accepts { "phone": "..." }
and only allows direct peers on private or loopback networks. Do not publish
this path through the public Ingress; callers must use the internal service
address. Forwarded client-IP headers are intentionally ignored.
Tests
go test ./...
go vet ./...
From the repository root, make test-db creates a disposable PostgreSQL
database and runs migration/maintenance integration tests.
Unit tests cover FIFO ticket/people selection, people-ahead ETA, phone
normalization, authenticated encryption, token hashing and password hashing.
PostgreSQL integration tests run through
make test-db against a disposable database.