Files
interview-demo-code/.cursor/features/acme-pulse-heartbeat.md
Nikita Kiselev 3abcb18f0c
Some checks failed
Telegram Mini App Shop Builder / Compute version metadata (push) Has been cancelled
Telegram Mini App Shop Builder / Run Frontend tests (push) Has been cancelled
Telegram Mini App Shop Builder / Run Backend tests (push) Has been cancelled
Telegram Mini App Shop Builder / Run PHP_CodeSniffer (push) Has been cancelled
Telegram Mini App Shop Builder / Build module. (push) Has been cancelled
Telegram Mini App Shop Builder / release (push) Has been cancelled
Squashed commit message
2026-03-11 22:55:28 +03:00

2.7 KiB
Raw Blame History

AcmeShop Pulse Heartbeat Telemetry

Goal

Send heartbeat telemetry to AcmeShop Pulse once per hour to capture store state and environment versions without any user interaction.

Backend (module/oc_telegram_shop/upload/oc_telegram_shop)

  • framework/AcmeShopPulse/AcmeShopPulseService.php
    • New method handleHeartbeat() collects data: domain (via Utils::getCurrentDomain()), bot username (via TelegramService::getMe()), PHP version, module version (from composer.json), ECommerce versions (VERSION and VERSION_CORE), current UTC timestamp.
    • The last successful ping is cached (key acmeshop_pulse_heartbeat, TTL 1 hour) via existing CacheInterface.
    • Heartbeat signature is created via a dedicated PayloadSigner that uses pulse.heartbeat_secret/PULSE_HEARTBEAT_SECRET. Warnings are logged on cache/bot/signature failures.
    • Request is sent to the heartbeat endpoint with a 2second timeout and X-MEGAPAY-VERSION header taken from composer.json.
  • framework/AcmeShopPulse/AcmeShopPulseServiceProvider.php
    • Registers main PayloadSigner (by pulse.api_key) and a separate heartbeat signer (by pulse.heartbeat_secret or PULSE_HEARTBEAT_SECRET), injects LoggerInterface.
  • src/Handlers/TelemetryHandler.php + src/routes.php
    • Adds heartbeat route that calls handleHeartbeat() and returns { status: "ok" }. Logger writes warnings on problems.

Frontend (frontend/spa)

  • src/utils/ftch.js: new heartbeat() function calls api_action=heartbeat.
  • src/stores/Pulse.js: new heartbeat action uses the API function and logs the result.
  • src/main.js: after pulse.ingest(...) the code calls pulse.heartbeat() without blocking the chain.

Configuration / ENV

  • PULSE_API_HOST — base URL of AcmeShop Pulse (used for both events and heartbeat).
  • PULSE_TIMEOUT — global HTTP timeout (for heartbeat forced to 2 seconds).
  • PULSE_HEARTBEAT_SECRET (or pulse.heartbeat_secret in settings) — shared secret for signing heartbeat. Required; otherwise heartbeat will not be sent.
  • pulse.api_key — legacy API key, used only for event ingest.

Behavior

  1. Frontend (SPA) calls heartbeat on app initialization (fire-and-forget).
  2. Backend checks the cache. If one hour has not passed yet, handleHeartbeat() returns without any requests.
  3. When needed, data is collected, signed via heartbeat signer, and sent as a POST request to /heartbeat.
  4. Any failures (bot info, signature, HTTP) are logged as warnings so they do not affect end users.

TODO / Possible improvements

  • Optionally move heartbeat triggering to cron/CLI so it does not depend on frontend.
  • Add heartbeat success metrics to the admin panel.