mirror of
https://github.com/tiennm99/tiennm99bot.git
synced 2026-10-11 03:13:46 +00:00
5.4 KiB
5.4 KiB
title, description, status, priority, effort, branch, tags, created, blockedBy, blocks, supersedes
| title | description | status | priority | effort | branch | tags | created | blockedBy | blocks | supersedes | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Go port of miti99bot to Google Cloud Run (free tier) | Full rewrite of the grammY/Cloudflare Worker bot in Go, deployed to Cloud Run with Firestore + Gemini + Cloud Scheduler — all free-tier. | planning | P2 | 5-7d | main |
|
2026-05-08 |
|
Plan: Go port → Google Cloud Run (free tier)
Full rewrite of miti99bot in Go for deployment on Cloud Run, swapping CF KV+D1+Workers AI for Firestore Native + Gemini API + Cloud Scheduler. Source repo lives at a new miti99bot-go repo (separate). Cutover via dual-run + soak.
Locked decisions
- Compute: Cloud Run (min-instances=0, scale-to-zero). Free tier: 2M req/mo, 360k vCPU-s, 180k GiB-s.
- Storage: Firestore Native, region
asia-southeast1. Free: 1 GiB, 50k reads/d, 20k writes/d. - AI: Gemini API via
google.golang.org/genai.text-embedding-004(768d) +gemini-1.5-flash. Free: 15 RPM / 1500 RPD per model. - Cron: Cloud Scheduler. 3 jobs/mo free → fits 2 current crons (
0 17 * * *,0 1 * * *). - Secrets: Secret Manager. Free: 6 active secret versions, 10k access ops/mo.
- Image registry: Artifact Registry. Free: 0.5 GiB storage.
- Telegram lib:
github.com/go-telegram/bot(modern, idiomatic, active). - Repo layout: separate
miti99bot-gorepo. JS/TS repo stays as-is during port. - Cutover: dual-run on test bot → flip prod webhook → 7-day overlap → decommission CF Worker.
Reports
- (none yet — research phase optional, only triggered if cold-start / quota assumptions need validation)
Phases
| # | Phase | Status | Effort | Key deliverable |
|---|---|---|---|---|
| 01 | GCP setup + free-tier baseline | pending | 3h | Hello-world Go on Cloud Run, cold-start P95 captured |
| 02 | New repo bootstrap + webhook skeleton | pending | 3h | miti99bot-go repo, /webhook validates secret token |
| 03 | Module framework + storage interfaces | pending | 4h | Module/Command/Cron interfaces, registry, dispatcher |
| 04 | Firestore KVStore + per-module prefixing | pending | 4h | FirestoreKVStore, emulator tests, in-memory fake |
| 05 | Port simple modules (util/misc/wordle/loldle) | pending | 6h | 4 KV-only modules at parity with JS version |
| 06 | Port loldle variants + lolschedule | pending | 5h | 5 modules sharing classic loldle patterns |
| 07 | Gemini AI + port semantle/doantu/twentyq | pending | 6h | 3 AI modules with rate-limit handling |
| 08 | Port trading + composite indexes | pending | 6h | VN-stocks paper trading + daily price cron |
| 09 | Cloud Scheduler cron wiring | pending | 2h | 2 jobs → /cron/{name} with OIDC |
| 10 | CI/CD + Dockerfile + Secret Manager | pending | 4h | GHA pipeline → AR → Cloud Run, idempotent |
| 11 | Test parity + observability | pending | 4h | Unit tests ported, Cloud Logging structured JSON |
| 12 | Cutover + decommission CF Worker | pending | 3h | Prod webhook flipped, soak passed, Worker retired |
Dependency graph
01 ──► 02 ──► 03 ──► 04 ──► 05 ──► 06 ─┐
├──► 07 ─────┤
└──► 08 ─────┤
03 ──────────► 09 ───────┤
02 ──────────► 10 ───────┤
08 ──► 11 ──► 12 ◄── 10
Free-tier budget at peak
| Resource | Cap | Expected | Headroom |
|---|---|---|---|
| Cloud Run req | 2M/mo | ~30k/mo | 99% |
| Cloud Run vCPU-s | 360k | ~5k | 99% |
| Firestore reads | 50k/day | ~5k/day | 90% |
| Firestore writes | 20k/day | ~2k/day | 90% |
| Cloud Scheduler jobs | 3 | 2 | 33% |
| Gemini RPM (flash) | 15 | <5 burst | 67% |
| Gemini RPD | 1500 | ~200 | 87% |
| Secret Manager versions | 6 | 3 | 50% |
| Artifact Registry storage | 0.5 GiB | <50 MiB | 90% |
If Firestore reads cap is hit → enable Cloud Run instance-level cache (warm-instance memo). If Gemini RPD cap is hit → degrade twentyq with a "free tier exhausted, retry tomorrow" reply.
Abort criteria
- Cold-start P95 > 1.5s sustained (Phase 01 baseline + Phase 11 soak): retain JS Worker for time-sensitive surfaces.
- Firestore reads > 80% of cap during Phase 11 soak: add KV-style instance cache before cutover.
- Gemini quota exhaustion during normal use: switch to lower-RPM-friendly Vertex AI (still free under credit) or accept degraded UX.
Rollback
Per-phase rollback documented in each phase file. Phase 12 is the only irreversible step; until then, the CF Worker continues to serve prod via existing webhook.
Open questions
- Scheduler cron names — keep
0 17 * * *(UTC) = midnight Saigon? Confirm timezone target. - Migrate KV/D1 data to Firestore (one-shot export) or start fresh on cutover? Trading has user-balance state worth preserving; loldle/wordle session state can reset.
- Test Telegram bot — reuse an existing dev bot, or create new
@miti99bot_dev?