Section 3/161 menit

3. Teori: Cara Kerja AsyncSequence dan Operator Pipeline

3. Teori: Cara Kerja AsyncSequence dan Operator Pipeline

Pull-based Model dan Back-pressure

AsyncSequence menggunakan model pull-based — consumer meminta elemen berikutnya dengan await next(), dan producer tidak menghasilkan elemen baru sampai diminta. Ini berbeda dari Combine/RxSwift yang push-based.

Back-pressure terjadi secara alami: jika consumer lambat memproses, producer akan tertahan di send() / yield() sampai consumer siap. Tidak ada overflow buffer secara default.

swift
Consumer (for await):       Producer (AsyncStream/Channel):
  |                               |
  |─── next() ──────────────────►|   consumer minta elemen
  |                               |─── hasilkan elemen ───►|
  |◄── elemen ────────────────── |
  |                               |
  |─── [memproses elemen] ───────|   consumer sibuk, producer menunggu
  |                               |
  |─── next() ──────────────────►|   consumer siap lagi

Cara Operator Bekerja

Setiap operator di Swift Async Algorithms adalah tipe yang conform ke AsyncSequence. Operator tidak menjalankan kode apapun sampai ada for await in — ini adalah lazy evaluation.

swift
chain(sequenceA, sequenceB)
    │
    └── adalah struct ChainSequence<A, B>: AsyncSequence
              iteratornya akan:
              1. iterate A sampai selesai
              2. baru iterate B

Ketika beberapa operator dirantai, terbentuk tree dari struct AsyncSequence yang saling membungkus — tidak ada data yang mengalir sampai consumer memulai iterasi.

AsyncChannel vs AsyncStream

Tipe Cocok Untuk Pengirim
AsyncStream Producer tunggal, tidak perlu await saat send Satu closure
AsyncChannel Multiple sender, back-pressure aware Multiple Task via await send()
AsyncThrowingChannel Seperti AsyncChannel + bisa throw error Multiple Task

AsyncChannel dari package ini berbeda dari AsyncStream bawaan Swift — AsyncChannel.send() adalah async dan akan menunggu jika consumer belum siap (back-pressure). AsyncStream.yield() tidak menunggu.

Clock Protocol

Operator time-based (debounce, throttle, chunked by duration) menggunakan Clock protocol dari Swift 5.7. Ini memungkinkan testing deterministik dengan MockClock tanpa menunggu waktu nyata.

swift
// Produksi: gunakan ContinuousClock (default)
let debounced = stream.debounce(for: .milliseconds(300))

// Testing: inject MockClock untuk kontrol waktu
let clock = TestClock()
let debounced = stream.debounce(for: .milliseconds(300), clock: clock)
await clock.advance(by: .milliseconds(300))  // simulasi waktu berlalu