PushizoDocs
Analitik & veri

Veri ambarına dışa aktarım

Pushizo; teslimat, olay, dönüşüm, kullanıcı ve abonelik verilerini düzenli olarak kendi veri ambarınıza aktarır: BigQuery, Snowflake veya S3 (Parquet). İlk çalıştırma geçmiş verinin tamamını, sonrakiler yalnızca yeni ve…

Pushizo; teslimat, olay, dönüşüm, kullanıcı ve abonelik verilerini düzenli olarak kendi veri ambarınıza aktarır: BigQuery, Snowflake veya S3 (Parquet). İlk çalıştırma geçmiş verinin tamamını, sonrakiler yalnızca yeni ve değişen satırları aktarır (docs/adr/0030-event-streams-ve-veri-ambari.md).

Yönetim: dashboard Geliştirici → Veri ambarı (organizasyon sahibi/yöneticisi) veya public API /v1/apps/{appId}/warehouse-exports (admin kapsamlı API anahtarı).

Tablolar

TabloTürİmleçNot
deliveriesartımlıupdated_atDurum her değiştiğinde yeni satır; güncel durum için id başına en büyük updated_at
delivery_eventsartımlıoccurred_atgönderildi, teslim edildi, açıldı, tıklandı …
eventsartımlıreceived_atÖzel olaylar; occurred_at istemci zamanıdır
conversionsartımlıattributed_atDönüşüm ve atıf
usersanlık görüntü—Günde bir (planlı çalıştırmada)
subscriptionsanlık görüntü—Cihaz token'ı ve hassas konum aktarılmaz

Her satırda ek kolonlar: _run_id (çalıştırma kimliği) ve _exported_at (dışa aktarım zamanı, UTC). Anlık görüntü tablolarında en güncel görüntü max(_exported_at) ile seçilir. Kolon listesi ve şema sürümleri GET /v1/apps/{appId}/warehouse-exports/tables ile okunur.

-- BigQuery: teslimatların güncel durumu
SELECT * EXCEPT(rn) FROM (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY id ORDER BY updated_at DESC) AS rn
  FROM `proje.pushizo.deliveries`
) WHERE rn = 1;
```text

Şema değişince kolonlar yalnızca **eklenir** (sona, boş değer kabul eden); hedef tablo bir sonraki çalıştırmada
güncellenir.

## Zamanlama ve güvenilirlik
- **Saatlik:** her saat başından 5 dk sonra; **günlük:** 00:15 UTC. "Şimdi çalıştır" ile elle tetiklenebilir
  (`POST …/warehouse-exports/{id}/run`); bekleyen veya süren bir çalıştırma varsa ya da dışa aktarım duraklatılmışsa
  `409` döner.
- Okuma, çalıştırma başlangıcından 5 dk öncesine kadar yapılır (geç tamamlanan işlemler kaçmaz; kalan kısım bir
  sonraki çalıştırmada gelir).
- Geçici hatalar (ağ, zaman aşımı, 429, 5xx) 1, 2, 4 dk aralıklarla yeniden denenir. Yarıda kalan çalıştırma son
  yazılan parçadan devam eder ve **çift satır üretmez** (parça bazında idempotent yazım).
- 3 ardışık başarısız çalıştırmada organizasyon sahip/yöneticilerine e-posta gönderilir ve denetim kaydı
  (`warehouse_export.failing`) oluşur. Son başarılı imleç korunduğundan sorun giderildiğinde veri kaybı olmaz.
- Çok büyük ilk aktarımlar parçalara bölünür: çalıştırma 20 dk sonra ilerlemeyi kaydedip kısmi biter, devamı
  dakikalar içinde otomatik başlar.

## BigQuery
1. Google Cloud'da bir servis hesabı oluşturun; projede **BigQuery Data Editor** ve **BigQuery Job User** rollerini verin.
2. Servis hesabı için JSON anahtar oluşturun ve içeriğini sihirbazdaki alana yapıştırın.
3. Proje kimliği, dataset (yoksa oluşturulur) ve konumu (`EU`, `US`, `europe-west3` …) girin.

Yükleme NDJSON **load job** ile yapılır (akış ücreti yok). Tablolar `_exported_at` üzerinde günlük bölümlüdür; JSON
alanlar `JSON` türündedir.

```bash
curl -X POST "$API/v1/apps/$APP_ID/warehouse-exports" -H "Authorization: Bearer $HS_KEY" -H 'content-type: application/json' -d '{
  "name": "BigQuery günlük",
  "destination": "bigquery",
  "config": { "project_id": "my-project", "dataset": "pushizo", "location": "EU" },
  "credentials": { "service_account_json": "<servis hesabı JSON içeriği, metin olarak>" },
  "tables": ["deliveries", "events", "conversions"],
  "schedule": "daily"
}'
```text

## Snowflake
**Önkoşul:** Pushizo veritabanı, şema ve warehouse **oluşturmaz** (yalnızca tabloları oluşturur ve kolon ekler).
Hedef veritabanı, şema ve warehouse sihirbazdan önce Snowflake'te var olmalıdır:
```sql
CREATE DATABASE IF NOT EXISTS ANALYTICS;
CREATE SCHEMA IF NOT EXISTS ANALYTICS.PUSHIZO;
CREATE WAREHOUSE IF NOT EXISTS LOAD_WH WITH WAREHOUSE_SIZE = 'XSMALL' AUTO_SUSPEND = 60 AUTO_RESUME = TRUE;
```text
Bunlar yoksa bağlantı testi ve çalıştırmalar `permission_denied` (nesne yok veya yetki yok) hatasıyla kalıcı olarak
başarısız olur.

1. Anahtar çifti oluşturun (şifresiz PKCS#8):
   ```bash
   openssl genrsa 2048 | openssl pkcs8 -topk8 -inform PEM -out rsa_key.p8 -nocrypt
   openssl rsa -in rsa_key.p8 -pubout -out rsa_key.pub
   ```text
2. Genel anahtarı kullanıcıya atayın ve yetki verin:
   ```sql
   ALTER USER HS_LOADER SET RSA_PUBLIC_KEY='MIIBIjANBgkqh…';
   GRANT USAGE ON WAREHOUSE LOAD_WH TO ROLE HS_LOADER_ROLE;
   GRANT USAGE ON DATABASE ANALYTICS TO ROLE HS_LOADER_ROLE;
   GRANT USAGE, CREATE TABLE ON SCHEMA ANALYTICS.PUSHIZO TO ROLE HS_LOADER_ROLE;
   ```text
3. Sihirbazda hesap tanımlayıcısı (`myorg-myaccount` veya `xy12345.eu-central-1`), kullanıcı, veritabanı, şema,
   warehouse, isteğe bağlı rol ve `rsa_key.p8` içeriğini girin.

Tablolar `CREATE TABLE IF NOT EXISTS` ile oluşturulur; JSON alanlar `VARIANT`, zamanlar `TIMESTAMP_TZ`'dir.

## S3 (Parquet)
- Bucket, bölge, anahtar öneki ve erişim anahtarı (yalnızca `s3:PutObject` ve bağlantı testi için `s3:DeleteObject`
  yeterli) girin. Cloudflare R2, MinIO gibi uyumlu depolamalar için özel uç verilebilir (iç ağ adresleri kabul edilmez).
- Dosya düzeni (Hive bölümleme, `dt` = dışa aktarım günü UTC):
  ```text
  <önek>/table=events/dt=2026-10-15/part-<çalıştırma>-0000.parquet
  ```text
- Dosyalar GZIP sıkıştırmalı Parquet'tir; Athena, Spark, DuckDB, BigQuery external table ve pandas/pyarrow doğrudan okur:
  ```sql
  -- DuckDB
  SELECT count(*) FROM read_parquet('s3://hs-lake/pushizo/table=events/dt=*/*.parquet', hive_partitioning = true);
  ```text

## Güvenlik
- Kimlik bilgileri zarf şifrelemeyle saklanır, API yanıtlarında ve denetim kayıtlarında yer almaz; yalnızca gizli
  olmayan özet gösterilir (servis hesabı e-postası, Snowflake anahtar parmak izi, maskeli erişim anahtarı).
- Kimlik bilgisini değiştirmek için düzenlemede `credentials` alanını yeniden gönderin.
- Yerel geliştirmede `PROVIDER_MODE=mock` iken BigQuery/Snowflake istekleri ağa çıkmaz (mock taşıyıcı); S3 her modda
  gerçek istemcidir (yerelde RustFS).

Bu sayfada