Pada proyek sebelumnya, Proyek: Pipeline Data CSV ke PostgreSQL, sumber data kita berupa berkas CSV yang sudah tersedia lengkap di disk. Kali ini sumber datanya hidup: sebuah REST API publik yang memotong respons menjadi halaman-halaman, membatasi jumlah permintaan, dan sesekali mengalami galat. Kita akan membangun pipeline ingestion yang mengambil data pesanan dari API publik fiktif TokoKita, memvalidasi bentuk responsnya, lalu menyimpan data mentah ke zona raw dalam format JSON Lines dengan dukungan mode incremental. Lima masalah khas ingestion dari API — pagination, rate limit, galat sementara, perubahan schema, dan pengambilan ulang data yang tidak berubah — kita selesaikan satu per satu pada tiap bagian proyek.

Arsitektur Ringkas #

Alur pipeline mengikuti pola extract yang tangguh sebelum data disentuh oleh transformasi apa pun:

Data mentah disimpan apa adanya di zona raw, sementara state kursor mencatat posisi terakhir ingestion agar run berikutnya bersifat incremental. Konsep zone dan cursor dibahas pada chapter Konsep Data Ingestion dan Incremental Ingestion.

Sumber Data API TokoKita #

API pesanan TokoKita bersifat fiktif dan menyediakan dua endpoint dengan kontrak berikut:

EndpointParameterKeterangan
GET /api/v1/pesananpage, per_pageDaftar pesanan terpaginasi dengan envelope data + meta
GET /api/v1/pesananupdated_sinceHanya pesanan dengan updated_at lebih baru dari nilai parameter
GET /api/v1/health-Pemeriksaan kesehatan sederhana

Server juga mensimulasikan perilaku API publik sesungguhnya: respons 429 dengan header Retry-After saat kuota terlampaui, galat 500 sesaat, dan tolakan 400 untuk parameter tidak valid.

Perilaku yang Diharapkan #

Sebuah eksekusi lengkap dijalankan dari akar bundle proyek dan mencetak ringkasan run berikut:

bash
python3 -m src.pipeline --mode full --demo

Output yang Dihasilkan (bagian ringkasan; log INFO di atasnya dipangkas):

text
=== Ringkasan Run ===
mode           : full
run_id         : 20261017T074428Z
baris_diambil  : 137
baris_duplikat : 0
baris_valid    : 137
baris_dilewati : 0
output         : data/raw/pesanan-20261017T074428Z.jsonl
kursor         : 2024-01-05T16:16:00+00:00

Run incremental berikutnya hanya mengambil pesanan baru sejak kursor terakhir:

bash
python3 -m src.pipeline --mode incremental --demo --demo-extra 5

Output yang Dihasilkan (bagian ringkasan):

text
=== Ringkasan Run ===
mode           : incremental
run_id         : 20261017T074435Z
baris_diambil  : 5
baris_duplikat : 0
baris_valid    : 5
baris_dilewati : 0
output         : data/raw/pesanan-20261017T074435Z.jsonl
kursor         : 2024-02-01T14:22:00+00:00

Seluruh perilaku pipeline dikunci oleh 52 tes pytest yang menjalankan fake server di localhost, sehingga setiap perubahan kode langsung terdeteksi.

Struktur Proyek #

text
pipeline-ingestion-api/
├── _index.md
├── part-1 ... part-9/
├── data/                  # zona raw JSON Lines + contoh respons
├── src/                   # fake_api, client, pagination, retry,
│                          # validator, storage, incremental, pipeline
├── tests/                 # conftest + 8 berkas tes pytest
└── config/                # pipeline.yaml, schema_pesanan.json, state kursor

Seluruh kode sumber proyek tersedia pada bagian Berkas Sumber di bawah halaman ini. Setiap bagian pengerjaan merujuk ke berkas yang sama, sehingga kondisi proyek tetap utuh di setiap tahap.

Tahapan Pengerjaan #

Proyek dikerjakan dalam sembilan bagian berurutan dan setiap bagian menghasilkan kode yang dapat dijalankan:

  1. Bagian 1 memahami kontrak API sumber dan menjalankan fake server lokal.
  2. Bagian 2 membangun klien HTTP dengan session, timeout, dan klasifikasi galat.
  3. Bagian 3 menjelajahi seluruh halaman respons dengan pola iterator.
  4. Bagian 4 menghormati rate limit lewat header Retry-After.
  5. Bagian 5 menerapkan retry dengan exponential backoff dan jitter.
  6. Bagian 6 memvalidasi schema respons sebelum data dipercaya.
  7. Bagian 7 menyimpan data mentah ke zona raw dalam format JSON Lines.
  8. Bagian 8 membuat ingestion incremental dengan state kursor updated_at.
  9. Bagian 9 menguji seluruh pipeline secara menyeluruh dengan pytest.

Mulailah dari Bagian 1 karena setiap bagian dibangun di atas hasil bagian sebelumnya.