Skip to content

Luồng đồng bộ dữ liệu (Sync Data Flow)

Tổng quan

Dịch vụ GMAC MEO tự động thực hiện đồng bộ dữ liệu và scraping xếp hạng tìm kiếm hàng ngày theo lịch định kỳ. Dữ liệu master từ 3 hệ thống khách hàng (GCOR, GMAC/Mappy, PIPIT) được tập hợp vào scraper DB, sau đó thực hiện scraping song song bằng AWS Batch, và ghi kết quả ngược lại về từng hệ thống.

Các hệ thống liên quan

Hệ thốngsystem_idDB ClusterMục đích
GMAC / Mappy1gmac-db-production-cluster-1DB khách hàng chính
GCOR2gcor-db-production-clusterDB khách hàng
PIPIT3kingmeo-db-production-clusterDB khách hàng
Scraper-scraper.cluster-*DB xử lý trung gian

Luồng tổng thể

Chi tiết từng bước

Step 1: sync_database

MụcGiá trị
Tên Lambdasync_database
RuntimePython 3.13
Timeout900 giây
RoleLambda_scraper
VPCCó (private subnet)
Thời gian chạy~2 phút

Xử lý:

  1. Kết nối đến 3 DB: GCOR, GMAC/Mappy, PIPIT
  2. Tạo bảng backup cho dữ liệu hiện tại (backup_*)
  3. Đồng bộ các bảng sau vào scraper DB:
    • mappy_user_settings
    • mappy_gbp_locations
    • mappy_gbp_locations_store_codes
    • mappy_integrated_gbp_locations
    • mappy_keywords
  4. Sau khi hoàn thành, phát custom event lên EventBridge:
    json
    {
      "detail-type": "SyncDatabaseCompleted",
      "source": "mappy.sync_db",
      "detail": {
        "status": "completed",
        "timestamp": "2026-04-07T17:02:13+09:00"
      }
    }

Biến môi trường (NEXT_LAMBDA_FUNCTION_NAME): fetch_search_ranking — tên Lambda sẽ được gọi tiếp theo.

Step 2: fetch_search_ranking

MụcGiá trị
Tên Lambdafetch_search_ranking
RuntimePython 3.13
Timeout900 giây
RoleTestCreateBatch-role-*
Thời gian chạy~47 giây

Xử lý:

  1. Được trigger bởi EventBridge event SyncDatabaseCompleted
  2. Submit 80 AWS Batch jobs:
    • Batch 1~40: normal (tìm kiếm thuận) — mỗi batch 350 keyword, Offset 0~13,650
    • Batch 41~80: reverse (tìm kiếm ngược) — mỗi batch 350 keyword, Offset 0~13,650
  3. Tổng cộng ~28,000 keyword được xử lý song song

Step 3: AWS Batch (Fargate)

MụcGiá trị
Job Definitionscraper_def
Job Queuescrap_queue
Compute Environmentscraper_env_v1 (Fargate)
Container Image881980194724.dkr.ecr.ap-northeast-1.amazonaws.com/scraper:latest
vCPU1.0
Memory2048 MB
Số container song songTối đa 80
Thời gian chạy~3-4 giờ

Xử lý:

  • Mỗi container dùng Playwright để thực hiện tìm kiếm Google và lấy dữ liệu xếp hạng
  • Kết quả được ghi vào scraper DB
  • Khi container hoàn thành, tăng counter total_batch_done

Step 4: reTry_Failed_Keywords

MụcGiá trị
Tên LambdareTry_Failed_Keywords
RuntimePython 3.14
Timeout900 giây
TriggerĐược gọi mỗi khi một Batch job hoàn thành
Thời gian chạy~100ms (chưa đủ) / ~2 giây (khi đủ điều kiện)

Xử lý:

  1. Được gọi bởi mỗi Batch container khi hoàn thành (callback)
  2. Kiểm tra bảng mst_systems trong scraper DB: so sánh total_batch_done với total_batch (=80)
  3. Nếu chưa đủ 80/80 → thoát ngay
  4. Khi tất cả batch hoàn thành (80/80):
    • Gọi lại fetch_search_ranking để retry các keyword thất bại

Step 5: syncResultFetchSearch

MụcGiá trị
Tên LambdasyncResultFetchSearch
RuntimePython 3.14
Timeout900 giây
RoleLambda_scraper
Memory5120 MB
Thời gian chạy~46 giây

Xử lý:

  1. Step 1: Đồng bộ kết quả tìm kiếm từ scraper DB về DB các hệ thống
    • mappy_search_ranking_exports
    • mappy_temp_search_rankings
  2. Step 2: Đồng bộ dữ liệu process
    • mappy_search_ranking_processes — cập nhật process_id
    • Cập nhật process_id cho exports và temp_rankings liên quan
  3. Step 2.5: Xử lý update logs
    • mappy_search_ranking_update_logs — cập nhật record ngày hiện tại (status=1)
    • Gán update_log_id cho các bảng liên quan
  4. Hậu xử lý:
    • Reset total_batch_done=0, retry_count=0 trong mst_systems
    • Tăng run_times thêm 1

Timeline (ví dụ chạy hàng ngày)

08:00 JST  sync_database bắt đầu
08:02 JST  sync_database hoàn thành → Phát event SyncDatabaseCompleted
08:02 JST  fetch_search_ranking khởi động → Submit 80 Batch jobs
08:03 JST  AWS Batch bắt đầu chạy (80 container song song)
   ...     Mỗi batch done → gọi reTry_Failed_Keywords
12:00 JST  Tất cả batch hoàn thành (80/80)
12:00 JST  fetch_search_ranking (retry) khởi động
   ...     Retry Batch cho keyword thất bại
12:30 JST  syncResultFetchSearch chạy
12:31 JST  Đồng bộ kết quả hoàn thành → Reset counter

Luồng sau khi tích hợp Places API Batch

Tích hợp Places API batch vào luồng hiện tại. Places API batch chạy song song với scraping batch. Điều kiện để đồng bộ kết quả (syncResultFetchSearch) thay đổi: cả scraping (80/80) VÀ Places API đều phải hoàn thành.

Thay đổi bảng mst_systems

CộtKiểuMô tả
total_batchintTổng số batch scraping (thay đổi tùy theo dữ liệu)
total_batch_doneintSố batch scraping đã hoàn thành
retry_countintSố lần retry
places_api_doneint(Mới) Cờ hoàn thành Places API batch (0=chưa, 1=xong)

Thay đổi so với luồng hiện tại

  1. Places API batch chạy cùng luồng (sau khi fetch_search_ranking submit scraping batch)
  2. Khi Places API batch hoàn thành → gọi Lambda event để update places_api_done = 1 trong mst_systems
  3. reTry_Failed_Keywords thay đổi điều kiện kiểm tra:
    • Hiện tại: chỉ check total_batch_done = total_batch
    • Sau khi tích hợp: check total_batch_done = total_batch places_api_done = 1
  4. Chỉ khi cả 2 điều kiện thỏa mãn → mới gọi syncResultFetchSearch để đồng bộ kết quả (bao gồm cả scraping + Places API) về 3 server

Sơ đồ luồng

Chi tiết xử lý

  1. fetch_search_ranking: Submit cả scraping batch (80 jobs) và Places API batch
  2. Scraping batch: 80 container Playwright chạy song song, mỗi container xong thì total_batch_done++
  3. Places API batch (places_api_def): Lấy ranking qua Google Places API (Text Search)
    • Container image: python310:latest
    • Chỉ xử lý location có data_source=1
    • Khi hoàn thành → gọi Lambda event update places_api_done = 1
  4. reTry_Failed_Keywords (thay đổi logic):
    • Được gọi mỗi khi một batch hoàn thành (callback)
    • Check mst_systems: total_batch_done = total_batch places_api_done = 1
    • Chưa đủ cả 2 → exit
    • Đủ cả 2 → gọi syncResultFetchSearch
  5. syncResultFetchSearch: Đồng bộ kết quả scraping + Places API từ scraper DB về 3 server (GCOR, GMAC, PIPIT)
  6. Hậu xử lý: Reset total_batch_done=0, retry_count=0, places_api_done=0

Timeline (sau khi tích hợp)

08:00 JST  sync_database bắt đầu
08:02 JST  sync_database hoàn thành → SyncDatabaseCompleted
08:02 JST  fetch_search_ranking khởi động
           → Submit 80 Scraping Batch jobs
           → Submit Places API Batch job
08:03 JST  Scraping + Places API chạy song song
   ...     Mỗi batch done → gọi reTry_Failed_Keywords
           (check: total_batch_done=total_batch AND places_api_done=1)
11:00 JST  Places API Batch hoàn thành → Lambda update places_api_done=1
12:00 JST  Scraping Batch hoàn thành (80/80)
12:00 JST  Cả 2 điều kiện thỏa → syncResultFetchSearch chạy
12:01 JST  Đồng bộ kết quả (Scraping + Places API) → Reset counter

Danh sách Lambda

Tên LambdaVai tròTimeoutMemory
sync_databaseĐồng bộ master data900s128 MB
fetch_search_rankingSubmit Batch jobs900s128 MB
reTry_Failed_KeywordsPolling batch + retry900s128 MB
syncResultFetchSearchĐồng bộ kết quả900s5120 MB
checkBatchStatusKiểm tra trạng thái batch3s128 MB
cloudwatch-to-slackGửi thông báo lỗi → Slack--

Tài nguyên liên quan

  • ECR: 881980194724.dkr.ecr.ap-northeast-1.amazonaws.com/scraper:latest
  • Batch Queue: scrap_queue (Fargate)
  • Batch Compute Env: scraper_env_v1
  • CloudWatch Log Groups:
    • /aws/lambda/sync_database
    • /aws/lambda/fetch_search_ranking
    • /aws/lambda/reTry_Failed_Keywords
    • /aws/lambda/syncResultFetchSearch
    • /aws/batch/job