Adımlar, mesafe, kalori, kalp atış hızı ve uyku verileri bir sağlık ve beslenme uygulaması tarafından kullanıcının platformundan (Android'de Android Health Connect, iOS'ta Apple HealthKit) çekilmeli ve tek, temiz, mükerrer kayıtlardan arındırılmış günlük bir profil olarak sunulmalıdır. İki API arasında çok az benzerlik bulunmaktadır: ayrı okuma mekanikleri, farklı yetkilendirme şemaları ve farklı veri yapıları. Biz, bunları tek bir platform gibi gösteren mobil senkronizasyon katmanını geliştirdik.
Zorluk
- Hiçbir konuda anlaşamayan iki yerel API. Apple HealthKit, geri çağrımlar (callbacks) aracılığıyla günlük toplu veriler döndürür; Health Connect ise zengin kaynak meta verileriyle ham, sayfalandırılmış örnekler döndürür. Aynı kavramlar, tamamen farklı yapılar — ve uygulama ikisini de tek bir şemaya normalize etmek zorundaydı.
- Varsayılan olarak çift sayma. Bir telefon, bir akıllı saat ve bir üçüncü taraf uygulama, aynı 8.000 adımı bildirebilir. Bunları basitçe toplamak her metrikte şişkinliğe neden olur. Uygulamanın çakışan kaynakları tanıması ve her gerçek dünya etkinliğini bir kez sayması gerekiyordu.
- Pil ve ağ, veri tazeliği için bedel ödeyemez. Sağlık verileri gün boyunca değişir, ancak her senkronizasyonda tüm geçmişi okumak pili tüketir ve hücresel bağlantıları doygunluğa ulaştırır. Senkronizasyon hızı, canlı bir deneyim sunarken hafif kalmalıydı.
İzinler kafa karıştırıcı olabilir. Düzinelerce veri türü, iki izin modeli, arka plan okuma kısıtlamaları ve bazı yetkilendirmeleri veren ancak diğerlerini vermeyen kullanıcılar — uygulamanın tüm bunları akışı bozmadan yönetmesi gerekir.
Çözümümüz
Biz üç katmanlı bir senkronizasyon geliştirdik: ince bir yerel katman her platformun API'ını okur, bir cihaz üzerinde normalleştirme katmanı verileri tekilleştirir ve günlük özetlere dönüştürür, arka uç ise bu verileri depolar ve tek bir güvenilir deftere (ledger) mutabık kılar. İstemci asla ham örnekler göndermez — bunun yerine temiz, saat dilimine göre doğru günlük özetleri gönderir.

Mimari
- iOS, Apple HealthKit verilerini react-native-health aracılığıyla okur; Android ise Health Connect verilerini react-native-health-connect aracılığıyla okur.
- Cihaz üzerinde normalleştirme, her iki platformun çıktısını tek bir şemaya dönüştürür ve telefon veri göndermeden önce mükerrer kayıtları temizler.
- Senkronizasyon tetikleyicileri — ilk başlatmada 30 günlük geçmiş, ardından 10 dakikalık aralıklarla ve her uygulama devam ettiğinde hafif 1 günlük artımlı okumalar.
- Taşıma — normalleştirilmiş günlük özetler, ana sunucunun /user-health/system-activity adresine POSTed edilir ve bu da onları (kullanıcı ID'si + saat dilimi ile birlikte) sağlık microservice'ine iletir.
- Kalıcılık — her kaynak/gün, bir HealthSystemAggregate olarak idempotent bir şekilde saklanır; bir MongoDB change stream daha sonra bunu güne özel bir HealthLedger içine mutabık kılar.
Yerel HealthKit ve Health Connect modülleriyle Expo / React Native yönetilen iş akışı.
Temel Özellikler
- İki API için tek bir normalleştirme sözleşmesi. Platforma özel okuyucular, kaynaktan bağımsız olarak aynı şekli veren tek bir formatHealthData adımını besler — böylece arka uç ve UI, iOS ile Android arasında asla ayrım yapmaz.
2. Cihaz üzerinde maksimuma dayalı tekilleştirme. Her kaynak içinde bir günün okumaları toplanır; ardından günlük değer, kaynaklar arasındaki Math.max() (source|deviceType ile anahtarlanmış kaloriler) olur, böylece tek bir cihazdan gelen birden fazla okuma birikirken, aynı günü bildiren bir saat ve bir telefon verileri ikiye katlamaz:
// Sum readings within each source, then take the max ACROSS sources dateSourceMap[date][source] += entry.count; const totalSteps = Math.ceil(Math.max(...Object.values(dateSourceMap[date]))); |
3.Platforma göre doğru okuma stratejisi. Health Connect okumaları bir pageToken döngüsü ile sayfalandırılır (sayfa başına 1.000 kayıt); HealthKit'in günlük toplu verileri gün gün döngüye alınır. Her özellik, uygulamanın geri kalanına görünmez olan kendi okuyucusunda bulunur.
4. Pili gözeten bir senkronizasyon ritmi. Tam 30 günlük geçmiş doldurma yalnızca bir kez çalışır (ilk çağrı bayrağıyla korunur); ondan sonra, her senkronizasyon yalnızca bir günü çeker — hücresel ağda hızlı, güç tüketimi açısından ucuzdur.
5. Saat dilimine göre doğru günlük gruplandırma. Örnekler, kullanıcının kendi saat diliminde YYYY-MM-DD anahtarlarına ayrılır, böylece akşam 11'deki bir antrenman, sunucunun nerede olduğuna bakılmaksızın doğru güne denk gelir.
6. Idempotent arka uç yazmaları. Her özet, (userId, deviceId, source, date) üzerine upsert yapar — aynı günün tekrar gönderilmesi bir no-op'tur, bu da yeniden denemeleri ve çakışan senkronizasyonları güvenli hale getirir.
7. Dürüst bozulma. Eksik izinler, boş okumalar ve Health Connect hız sınırı hataları yakalanır ve düzgün bir şekilde gösterilir — boş bir gün senkronizasyonu asla çökertmez ve kullanıcıya sessiz bir hata yerine açık bir uyarı verilir.
Sonuçlar
- iOS ve Android genelinde tek, tutarlı bir sağlık profili — platform farkı uygulamanın geri kalanı için görünmezdir.
- Çakışan cihaz/uygulama kaynakları tekilleştirilir, böylece adımlar ve kaloriler şişirilmiş toplamlar yerine gerçeği yansıtır.
- Hafif artımlı senkronizasyonlar, pili tüketmeden veya mobil veri harcamadan verileri güncel tutar.
Saat dilimine göre doğru, idempotent yazmalar, her metriğin doğru güne denk gelmesi anlamına gelir ve yeniden denemeler kaydı asla bozmaz.
Teknoloji Yığını
React Native (Expo) · react-native-health (HealthKit) · react-native-health-connect · NestJS · MongoDB · MongoDB Change Streams · moment-timezone

