Memproses analitik riwayat Git commit secara massal menggunakan Large Language Model (LLM) sering kali memicu pemborosan token dan kegagalan rate-limit. Saat push berskala besar terjadi di banyak repositori secara bersamaan, sistem background worker rentan memproses duplikasi commit yang sama dari merge branch atau rebase. Artikel ini merancang pipeline ringkasan Git commit yang efisien dengan menggabungkan job queue, deduplikasi commit hash berbasis Redis atomic locks, dan multi-tier caching (PostgreSQL dan Redis).

Arsitektur Sistem Analitik Commit Terdistribusi

Pipeline analitik commit dirancang secara asinkron guna mengisolasi webhook ingestor dari latensi eksekusi LLM. Diagram alur operasionalnya adalah sebagai berikut:

  1. Ingestion: Git webhook mengirimkan commit payload ke ingestion service. Ingestion service hanya memvalidasi signature dan melempar array hash commit ke job queue (misalnya RabbitMQ atau Redis Stream).
  2. Deduplication Guard: Worker mengambil commit ID dan mengecek layer deduplikasi menggunakan Redis distributed lock sebelum parsing git diff.
  3. Cache Lookup: Worker memeriksa apakah ringkasan commit sudah tersimpan di database relasional atau Redis cache.
  4. Batching & Inference: Jika cache miss, commit diff digabungkan dalam micro-batch yang diatur token bucket limiter sebelum dikirim ke API LLM.
  5. Storage: Hasil ringkasan disimpan permanen ke database dan status kunci Redis diperbarui.

Deduplikasi Payload Menggunakan Redis Lock

Ketika developer melakukan rebase atau merge commit antar branch, hash SHA-1 atau SHA-256 yang identik dapat dikirim berkali-kali dalam hitungan detik. Mengirim payload ini berulang kali ke LLM membuang kuota API.

Deduplikasi diselesaikan pada level worker menggunakan Redis command SET key value NX EX. Perintah ini hanya menyetel key jika belum ada (Not eXists) dan memberikan waktu kedaluwarsa (TTL) secara atomik.

import redis
import time

r = redis.Redis(host='localhost', port=6379, db=0)

def acquire_commit_lock(commit_hash: str, lock_timeout: int = 60) -> bool:
    lock_key = f"lock:commit:{commit_hash}"
    # Nilai 1 disetel hanya jika key belum ada; TTL mencegah dead-lock jika worker crash
    is_acquired = r.set(lock_key, "processing", nx=True, ex=lock_timeout)
    return bool(is_acquired)

def release_commit_lock(commit_hash: str):
    r.delete(f"lock:commit:{commit_hash}")

Jika acquire_commit_lock mengembalikan False, worker langsung menandai task tersebut sebagai duplicate dan mengabaikannya tanpa memproses diff atau memanggil LLM.

Multi-Tier Caching untuk Mencegah Token Exhaustion

Sebuah commit bersifat immutable; konten perubahan pada satu hash commit tidak akan pernah berubah. Maka dari itu, hasil ringkasan teks commit dapat di-cache secara permanen.

Layer 1: SQL Persistent Store

Tabel PostgreSQL bertindak sebagai source of truth. Skema memuat indeks unik pada commit hash untuk menjamin integritas data di level basis data:

CREATE TABLE commit_summaries (
    id BIGSERIAL PRIMARY KEY,
    commit_hash VARCHAR(64) UNIQUE NOT NULL,
    repo_id VARCHAR(100) NOT NULL,
    summary_text TEXT NOT NULL,
    tokens_used INT NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_commit_hash ON commit_summaries (commit_hash);

Layer 2: Fast Read-Through Cache (Redis)

Sebelum melakukan query ke SQL atau menjalankan inferensi LLM yang mahal, worker membaca string cache dari Redis key summary:{commit_hash}. Alur validasi cache dilakukan bertingkat:

def get_or_generate_summary(commit_hash: str, diff_text: str) -> str:
    cache_key = f"summary:{commit_hash}"
    
    # 1. Cek Redis In-Memory
    cached = r.get(cache_key)
    if cached:
        return cached.decode('utf-8')
        
    # 2. Cek SQL DB
    db_summary = query_summary_from_db(commit_hash)
    if db_summary:
        r.setex(cache_key, 86400, db_summary) # Simpan 24 jam di Redis
        return db_summary
        
    # 3. Cache Miss: Jalankan Inferensi LLM
    summary = call_llm_inference(diff_text)
    save_to_db(commit_hash, summary)
    r.setex(cache_key, 86400, summary)
    
    return summary

Mitigasi Rate-Limit: Token Bucket & Micro-Batching

Penyedia API AI membatasi traffic berdasarkan Requests Per Minute (RPM) dan Tokens Per Minute (TPM). Memproses 500 commit push events secara individual memicu error HTTP 429 Too Many Requests.

Untuk mengatasinya, worker dirancang mengumpulkan diff dalam jendela waktu 2 detik (micro-batch) hingga mencapai batas maksimal token sebelum dikirim dalam 1 API call, dikontrol oleh algoritma Token Bucket.

class TokenBucketRateLimiter:
    def __init__(self, capacity: int, fill_rate: float):
        self.capacity = capacity
        self.fill_rate = fill_rate
        self.tokens = capacity
        self.last_update = time.monotonic()

    def consume(self, tokens_needed: int) -> bool:
        now = time.monotonic()
        elapsed = now - self.last_update
        self.last_update = now
        
        self.tokens = min(self.capacity, self.tokens + elapsed * self.fill_rate)
        
        if self.tokens >= tokens_needed:
            self.tokens -= tokens_needed
            return True
        return False

Jika token tidak mencukupi, job di-requeue atau ditunda menggunakan exponential backoff dengan jitter guna mencegah thundering herd problem pada endpoint penyedia LLM.

Debugging dan Edge Cases

  • Worker Crash Saat Memegang Lock: Jika worker mati mendadak sebelum melepas lock, parameter EX pada perintah Redis memastikan key terhapus otomatis setelah batas TTL berakhir, menghindari kondisi stale lock.
  • Truncation pada Commit Raksasa: Commit berupa merge besar atau regenerasi file lock dapat melebihi context window LLM. Terapkan pemotongan statis (misal: maksimum 4.000 token diff per commit) sebelum memicu inferensi LLM.
  • Pencocokan Duplikat Lintas Branch: Pastikan deduplikasi memakai kombinasi repo_id:commit_hash jika worker melayani repositori multi-tenant, guna mencegah tabrakan hash non-kriptografis antar repositori yang berbeda.