Services
Cloudflare TMap worker
Backend tuỳ chọn gồm Cloudflare Worker và cơ sở dữ liệu D1 để sao lưu TMap (bản đồ ticket → vòng DCA) của GoldenRobber và bầu leader khi nhiều node chạy cùng tài khoản. Trang này mô tả endpoint, schema, cách deploy bằng wrangler và trạng thái hiện tại. An optional Cloudflare Worker + D1 backend that backs up GoldenRobber's TMap (ticket → DCA round map) and elects a leader when several nodes run the same account. This page covers the endpoints, schema, deploying with wrangler, and its current status.
Trạng thái hiện tạiCurrent status
Trong cả hai config pass58 (v1.41.4-pass58-easupported-goldenrobber-29082026.set và v1.42.b7-pass58.set): InpCloudSyncEnable=true, InpCloudCfDomain để trống, InpCloudMyApiDomain=https://fxconsole.gamelau.uk/easupported/goldenrobber. Nghĩa là EA production chỉ đồng bộ TMap lên fxconsole (MyApi), không gọi Worker này.
In both pass58 configs (v1.41.4-pass58-easupported-goldenrobber-29082026.set and v1.42.b7-pass58.set): InpCloudSyncEnable=true, InpCloudCfDomain is empty, InpCloudMyApiDomain=https://fxconsole.gamelau.uk/easupported/goldenrobber. The production EA therefore syncs TMap only to fxconsole (MyApi) and never calls this Worker.
wrangler.toml trong repo vẫn giữ database_id = "REPLACE_WITH_YOUR_D1_DATABASE_ID", nên repo không cho thấy một bản Worker nào đang được deploy (chưa xác minh trên tài khoản Cloudflare).
wrangler.toml in the repo still holds database_id = "REPLACE_WITH_YOUR_D1_DATABASE_ID", so the repo shows no deployed Worker instance (not verified against the Cloudflare account).
EA dùng Worker thế nàoHow the EA uses it
Từ v1.38 EA chỉ nhận domain; EA tự nối đường dẫn: Worker dùng /tmap/{save,load,clear,heartbeat}, fxconsole (MyApi) dùng /api/tmap/{save,load,clear,heartbeat}. Hai backend có cùng hợp đồng API và dùng chung một Bearer token (InpCloudBearerToken).
- Save: gửi toàn bộ TMap lên từng backend có domain (POST
/save), theo chu kỳInpCloudSyncIntervalSec. - Clear: khi không còn lệnh nào (
nPos == 0), gọi DELETE/cleartrên cả hai backend. - Load: khi cần khôi phục, EA có hàm đọc từ Worker (D1) và từ MyApi; chỉ chạy khi
InpCloudSyncEnable=truevà không ở Strategy Tester. - Heartbeat / leader: thử Worker trước, lỗi thì sang MyApi. Nếu cả hai lỗi quá
2 × InpCloudHeartbeatTimeoutSec, node tự nhận làm leader để không chặn giao dịch.
Since v1.38 the EA takes a domain only and appends the paths itself: the Worker uses /tmap/{save,load,clear,heartbeat}, fxconsole (MyApi) uses /api/tmap/{save,load,clear,heartbeat}. Both backends share the same API contract and the same Bearer token (InpCloudBearerToken).
- Save: posts the whole TMap to every backend that has a domain (POST
/save), everyInpCloudSyncIntervalSec. - Clear: when no positions remain (
nPos == 0), calls DELETE/clearon both backends. - Load: for recovery the EA has loaders for the Worker (D1) and for MyApi; they only run with
InpCloudSyncEnable=trueand never in the Strategy Tester. - Heartbeat / leader: tries the Worker first, falls back to MyApi. If both fail for longer than
2 × InpCloudHeartbeatTimeoutSec, the node declares itself leader so trading isn't blocked.
flowchart LR
EA["GoldenRobber EA"] -- "HTTPS /tmap/* (nếu InpCloudCfDomain có giá trị)" --> CF["Cloudflare Worker gr-tmap"]
CF --> D1[("D1: tmap_entries, tmap_nodes")]
EA -- "HTTPS /api/tmap/* (production)" --> FX["fxconsole TmapApiController"]
EA -. "heartbeat: Worker trước, MyApi dự phòng" .-> CFflowchart LR
EA["GoldenRobber EA"] -- "HTTPS /tmap/* (when InpCloudCfDomain is set)" --> CF["Cloudflare Worker gr-tmap"]
CF --> D1[("D1: tmap_entries, tmap_nodes")]
EA -- "HTTPS /api/tmap/* (production)" --> FX["fxconsole TmapApiController"]
EA -. "heartbeat: Worker first, MyApi fallback" .-> CFQuy trình khôi phục chi tiết: Khôi phục TMap.Full recovery procedure: TMap disaster recovery.
Input Cloud sync trong EACloud sync inputs in the EA
| Input | Mặc định EAEA default | pass58 | Ý nghĩaMeaning |
|---|---|---|---|
InpCloudSyncEnable | false | true | Bật đồng bộ TMap lên cloud (chỉ live)Enable TMap cloud sync (live only) |
InpCloudBearerToken | trốngempty | <secret> | Bearer token, dùng chung cho cả hai backendBearer token, shared by both backends |
InpCloudCfDomain | trốngempty | trốngempty | Domain Worker, ví dụ https://gr-tmap.your-account.workers.devWorker domain, e.g. https://gr-tmap.your-account.workers.dev |
InpCloudMyApiDomain | trốngempty | https://fxconsole.gamelau.uk/easupported/goldenrobber | Domain fxconsole (không thêm /api/tmap)fxconsole domain (do not add /api/tmap) |
InpCloudSyncIntervalSec | 30 | 10 | Chu kỳ đồng bộ (giây)Sync interval (seconds) |
InpCloudWebTimeoutMs | 5000 | — | Timeout WebRequest (ms)WebRequest timeout (ms) |
InpCloudNodePriority | 100 | 100 | Ưu tiên node, số nhỏ ưu tiên cao (1–999)Node priority, lower wins (1–999) |
InpCloudNodeId | trốngempty | trốngempty | ID node duy nhất; trống = tự lấy từ terminalUnique node ID; empty = derived from the terminal |
InpCloudHeartbeatTimeoutSec | 90 | 90 | Node bị coi là chết nếu không heartbeat trong N giâyA node counts as dead after N seconds without a heartbeat |
cloudflare-tmap-worker/README.md còn nhắc InpCloudSecretKey và InpCloudCfUrl. Từ v1.38 URL đổi thành InpCloudCfDomain (chỉ domain) và token nằm ở InpCloudBearerToken. Config cũ còn đuôi /tmap hoặc /api/tmap sẽ tạo URL sai, phải bỏ đuôi đó trong .set.
cloudflare-tmap-worker/README.md still mentions InpCloudSecretKey and InpCloudCfUrl. Since v1.38 the URL input is InpCloudCfDomain (domain only) and the token is InpCloudBearerToken. Old configs that keep a /tmap or /api/tmap suffix build wrong URLs; remove the suffix in the .set.
API endpointAPI endpoints
Mọi request (trừ preflight OPTIONS) phải có header Authorization: Bearer <secret> khớp với secret TMAP_SECRET_KEY của Worker; nếu Worker chưa có secret hoặc token sai → 401 {"message":"Unauthorized"}. Worker trả CORS * cho GET, POST, DELETE, OPTIONS.
Every request (except the OPTIONS preflight) needs Authorization: Bearer <secret> matching the Worker's TMAP_SECRET_KEY secret; a missing secret on the Worker or a wrong token → 401 {"message":"Unauthorized"}. The Worker answers CORS * for GET, POST, DELETE, OPTIONS.
| Method | Path | Hành viBehaviour | Kết quảResponse |
|---|---|---|---|
| POST | /tmap/save | Thay toàn bộ map của magic+account: xoá rồi insert batchReplaces the whole map for magic+account: delete, then batch insert | {ok, count} |
| GET | /tmap/load?magic=…&account=… | Đọc mapReads the map | {ok, magic, account, entries} |
| DELETE | /tmap/clear?magic=…&account=… | Xoá mapDeletes the map | {ok, deleted} |
| POST | /tmap/heartbeat | Upsert heartbeat của node rồi bầu leader trong các node còn sống (priority tăng dần, rồi node_id)Upserts the node heartbeat, then elects a leader among live nodes (priority ascending, then node_id) | {ok, is_leader, current_leader_id, current_leader_priority, alive_count, alive_nodes} |
Lỗi: thiếu trường → 422; đường dẫn khác → 404 Not found; exception → 500 {"message":"Server error","error":…}. README Worker chỉ liệt kê ba endpoint đầu; /tmap/heartbeat có trong src/index.js.
Errors: missing fields → 422; any other path → 404 Not found; an exception → 500 {"message":"Server error","error":…}. The Worker README lists only the first three endpoints; /tmap/heartbeat exists in src/index.js.
Body của saveSave body
{
"magic": "21478308",
"account": "12345",
"entries": [
{
"ticket": 100,
"round_id": 5,
"add_num": 2,
"is_dca_pos": true,
"pos_type": 0,
"comment": "DCAPos R5 B#2 |add_minpips"
}
]
}
Body của heartbeatHeartbeat body
Bắt buộc magic, account, node_id, priority; tuỳ chọn timeout_sec (mặc định 90). Node được coi là sống nếu last_heartbeat trong vòng timeout_sec giây.
Requires magic, account, node_id, priority; optional timeout_sec (default 90). A node is alive if its last_heartbeat is within timeout_sec seconds.
{"magic":"21478308","account":"12345","node_id":"vps-tokyo","priority":100,"timeout_sec":90}
Schema D1D1 schema
| BảngTable | CộtColumns | KhoáKeys |
|---|---|---|
tmap_entries | id, magic, account, ticket, round_id, add_num, is_dca_pos, pos_type, comment, updated_at | UNIQUE(magic, account, ticket), indexindex (magic, account) |
tmap_nodes | id, magic, account, node_id, priority, last_heartbeat (unix timestamp)(unix timestamp) | UNIQUE(magic, account, node_id), indexindex (magic, account) |
Deploy bằng wranglerDeploy with wrangler
-
Cài Wrangler CLI (trong
cloudflare-tmap-worker/):Install the Wrangler CLI (incloudflare-tmap-worker/):npm install npm install -g wrangler wrangler login -
Tạo database D1:Create the D1 database:
Output có dạng dưới đây. Copynpm run db:createdatabase_iddán vàowrangler.tomlthay choREPLACE_WITH_YOUR_D1_DATABASE_ID.The output looks like this. Copydatabase_idintowrangler.tomlin place ofREPLACE_WITH_YOUR_D1_DATABASE_ID.✅ Successfully created DB 'gr-tmap' [[d1_databases]] binding = "DB" database_name = "gr-tmap" database_id = "abc123-def456-..." -
Áp schema:Apply the schema:
npm run db:migrate -
Đặt secret: lệnh hỏi giá trị secret; nhập trực tiếp, không lưu vào file.Set the secret: the command prompts for the value; type it there, never save it in a file.
Secret này phải giống token trong EA (npm run secret:setInpCloudBearerToken, tên cũ trong README làInpCloudSecretKey) vàTMAP_SECRET_KEYtrong.envcủa fxconsole.This secret must be identical to the EA token (InpCloudBearerToken; the README's old name isInpCloudSecretKey) and toTMAP_SECRET_KEYin fxconsole's.env. -
Deploy:Deploy:
npm run deploy
URL này dùng làm✨ Deployed gr-tmap triggers (1 sec) https://gr-tmap.your-account.workers.devInpCloudCfDomaintrong EA (chỉ domain; README ghi tên cũInpCloudCfUrl). Nhớ thêm domain vào danh sách WebRequest được phép của MT5.Use this URL as the EA'sInpCloudCfDomain(domain only; the README uses the old nameInpCloudCfUrl). Remember to add the domain to MT5's allowed WebRequest URLs.
Script npmnpm scripts
| Script | LệnhCommand |
|---|---|
dev | wrangler dev |
deploy | wrangler deploy |
db:create | wrangler d1 create gr-tmap |
db:migrate | wrangler d1 execute gr-tmap --file=schema.sql --remote |
db:migrate-local | wrangler d1 execute gr-tmap --file=schema.sql --local |
secret:set | wrangler secret put TMAP_SECRET_KEY |
Kiểm traTest
curl -X POST https://gr-tmap.your-account.workers.dev/tmap/save \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <secret>" \
-d '{"magic":"123","account":"test","entries":[]}'
Kết quả mong đợi: {"ok":true,"count":0}. Nhận 401 nghĩa là secret chưa đặt hoặc token sai.
Expected: {"ok":true,"count":0}. A 401 means the secret isn't set or the token is wrong.