TL;DR
- Bir bilet kontrol uygulaması canlı Wi-Fi’ye bağımlı olamaz: taramalar çevrimdışı çalışmalı ve daha sonra senkronize edilmelidir.
- Dört uç nokta işlev görüyor: manifest indirme, idempotent toplu gönderim, delta çekme, çevrimiçi arama.
- Müşteri tarafından oluşturulan UUID’ler + benzersiz bir indeks, yeniden denemelerin güvenli olmasını sağlar. Duplicatlar bir başarı durumu olup hata değildir.
<h2>
<a name="the-problem" href="#the-problem"></a>
Problemin Tanımı
</h2>
<p>Fiziksel bir etkinlikte, personel kapıda biletleri tararken, mekanın Wi-Fi'sinin güvenilirliği tahmin ettiğiniz gibi. Eğer API'niz her taramanın sıcak yolunda yer alıyorsa, kapıdaki kuyruk, binanın en kötü sinyal çubuğu hızında büyümektedir.</p>
<p>Tasarımı böylece tersine çeviriyoruz: <strong>cihaz check-in'i, sunucu ise uzlaşmayı sahipleniyor.</strong> Kasiyerin kasası kapandığında bir kağıt defteri tutmasına benzer — şimdi kaydet, daha sonra uzlaştır.</p>
<h2>
<a name="the-api-surface" href="#the-api-surface"></a>
API Arayüzü
</h2>
<div class="table-wrapper-paragraph">
<table>
<thead>
<tr>
<th>Uç Nokta</th>
<th>Amacı</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>GET /staff/events/{uuid}/manifest</code></td>
<td>kapı açılmadan önce indirilen sayfalandırılmış bilet özeti</td>
</tr>
<tr>
<td><code>POST /staff/events/{uuid}/check-ins/batch</code></td>
<td>kuyrukta bekleyen taramaları gönder; yeniden denemek güvenlidir</td>
</tr>
<tr>
<td><code>GET /staff/events/{uuid}/check-ins?since=<cursor/></code></td>
<td>diğer cihazların yaptığı taramaları al</td>
</tr>
<tr>
<td><code>GET /staff/events/{uuid}/participants?q=</code></td>
<td>çevrimiçi yedek arama (kaybolan bilet, yazım hatası)</td>
</tr>
</tbody>
</table>
</div>
<h2>
<a name="the-sync-loop" href="#the-sync-loop"></a>
Senkronizasyon Döngüsü
</h2>
<div class="highlight js-code-highlight">
<pre class="highlight plaintext"><code>Device Server|— GET manifest (before event) ——->|
| scan offline, queue locally |
|— POST batch [{client_uuid, ts}] —->| dedupe on client_uuid
|| scans from other devices
|
<h2>
<a name="idempotency-is-the-whole-trick" href="#idempotency-is-the-whole-trick"></a>
Idempotency Tüm Sır
</h2>
<p>Her tarama, <strong>tarama zamanında cihazda üretilen bir UUID</strong> alır. Sunucu buna benzersiz bir indeks koyar ve ekler veya yok sayar:</p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="k">public</span> <span class="k">function</span> <span class="n">batchCheckIn</span><span class="p">(</span><span class="kt">BatchCheckInRequest</span> <span class="nv">$request</span><span class="p">,</span> <span class="kt">string</span> <span class="nv">$uuid</span><span class="p">):</span> <span class="kt">JsonResponse</span>{
$results = collect($request->validated(‘check_ins’))->map(function (array $scan) {
$checkIn = CheckIn::firstOrCreate(
[‘client_uuid’ => $scan[‘client_uuid’]],
[‘ticket_id’ => / resolved from scan /, ‘checked_in_at’ => $scan[‘scanned_at’]],
// …
);
return [
‘client_uuid’ => $scan[‘client_uuid’],
‘status’ => $checkIn->wasRecentlyCreated ? <span class=”s1>’applied’ : <span class=”s1>’duplicate’,
];
});
<span class="k">return</span> <span class="nf">response</span><span class="p">()</span><span class="o">-></span><span class="nf">json</span><span class="p">([</span><span class="s1>'results'</span> <span class="o">=></span> <span class="nv">$results</span><span class="p">]);</span>}


