5.5 KiB
Operating ecomm
The framework-repo operator guide (SD-0002 DOC-1), started at SLICE-5. It covers
the app's operational surface — telemetry, runbooks, alert gestures, the E2E
gate. Per-deployment mechanics (deploy, secrets, VM access) live in the
deployment's flotilla docs and deployment.toml; environment bring-up is in
BOOTSTRAP.md.
Products import/export ops (SD-0002, SLICE-5)
The §6.4 surface: a merchant uploads a catalog CSV (POST /api/products/imports), the app validates it and stores an import draft
with a full preview (adds / updates / unchanged / errors), the merchant
confirms or cancels at the preview gate, and a confirm applies the previewed
diff as one import run recorded in the history (/api/products/imports/runs).
Caps and behavior to know (all enforced in code, not config):
- Caps (INV-18): ≤ 5,000 data rows and ≤ 10 MB per file —
MAX_DATA_ROWS/MAX_FILE_BYTESinbackend/app/domains/products/models.py, enforced inbackend/app/domains/products/codec.py(file-level rejection) plus a 413file_too_largeguard in the BFF (backend/app/main.py). - Draft expiry: ~1 hour (
expires_at = now() + interval '1 hour'). Cleanup is a lazy sweep — expired drafts are deleted on the next upload and on any access to an expired draft; there is no background job to babysit. - Upsert-only (INV-10): an import adds and updates, never deletes. Catalog products/variants/images absent from the file are untouched.
- One-transaction apply (INV-11): a confirm applies the whole previewed diff in a single DB transaction — it lands completely or not at all.
Telemetry
Structured JSON events on the ecomm.telemetry logger
(backend/app/platform/telemetry.py), one JSON object per line, emitted from
backend/app/domains/products/service.py. The app's ecomm.* log handler
writes to the process's stderr, which journald captures on the VM (and Cloud
Logging where the agent ships it). Events carry counts and durations only —
never file names, URLs, catalog content, or secret bytes.
| Event | Trigger | Payload fields |
|---|---|---|
TEL-1 import_draft_created |
validation completes, draft stored | storefront_id, dialect, row_count, adds, updates, unchanged, errors, unknown_columns_count, duration_ms |
TEL-2 import_run_completed |
apply transaction commits | run_id, storefront_id, added, updated, errored, duration_ms |
TEL-6 import_apply_failed |
apply transaction aborts unexpectedly | draft_id, storefront_id, error_class |
RB-2 — import apply failed
Triggered by ALR-2 (any TEL-6 event). The apply raised mid-transaction and rolled back.
-
Locate the failure. On the VM, filter the journal for the event and note the
draft_id,storefront_id, anderror_class:journalctl -u ecomm.service | grep import_apply_failed -
Confirm the rollback held (INV-11). The apply is one transaction, so a failure leaves the catalog exactly as it was: the storefront's runs history (
GET /api/products/imports/runs) shows no new run, and the products summary (GET /api/products/summary) shows an unchangedproduct_count. -
The merchant's draft is intact. A failed apply does not consume the draft — the merchant can retry confirm, or re-upload if the draft has since expired (~1 h). Advise accordingly.
-
File a bug on
wiggleverse/wiggleverse-ecommwith theerror_classand the surrounding log context (the traceback is in the app log next to the event).
ALR-2 — the log-based alert (one gesture per environment)
Run once per environment, at this slice's PPE deploy. This is an ad hoc op on
the existing GCP project (wiggleverse-ecomm), not a provisioning gesture.
# Select the deployment's gcloud config for this one process (handbook §8.4).
export CLOUDSDK_ACTIVE_CONFIG_NAME=wiggleverse-ecomm
# Log-based metric counting import-apply failures (TEL-6).
gcloud logging metrics create ecomm_import_apply_failed \
--description="ecomm TEL-6 import_apply_failed events (SD-0002 ALR-2)" \
--log-filter='resource.type="gce_instance" AND jsonPayload.message:"import_apply_failed" OR textPayload:"import_apply_failed"'
Then attach an alert policy to the metric — operator email channel, threshold
any event > 0 in 5 minutes, severity notify-only (pre-v1: no paging). The
policy is created in the Cloud Console or with
gcloud alpha monitoring policies create; the exact command depends on the
notification-channel id, so list channels first:
# Find the operator email channel's id for the policy.
gcloud beta monitoring channels list
E2E browser suite
- Lives at
e2e/— Playwright, Chromium, four SLICE-5 scenarios (preview/confirm happy path, actionable errors, file rejection, cancel). - Run with
bash scripts/e2e.sh. The harness boots a freshecomm_e2edatabase against the local compose Postgres and serves the built SPA from the backend on :8765 (the deployed topology), so it needs the dev Postgres up (scripts/dev.sh). - Not in
scripts/check.sh/ CI yet — the Gitea runner has no browsers (the §10.6 machinery gap). Run it locally before merge, and against PPE per the §9 pipeline (the PPE browser run is still manual this slice).
Cross-references
- SLO and alert definitions: SD-0002 §9–§10 (content repo,
wiggleverse-ecomm-content/specs/SD-0002-products-bulk-csv-import-export.md). - Import/diff engine internals:
products-domain.md.