feat(backend): migration mekanizması, indeksler ve ortak model yardımcıları

- db/migrations.rs: schema_migrations ile sürümlü migration (v1: koleksiyonlar)
- db/indexes.rs: DATA_MODEL indeksleri + senkronizasyon indeksi, açılışta otomatik
- models/common.rs: UUID v7, ortak alanlar, hane kapsamlı filtre
- Birim testleri (4)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-11 23:25:55 +03:00
parent 8ec24ecec2
commit 5550c7c43d
13 changed files with 367 additions and 34 deletions
View File
+70
View File
@@ -0,0 +1,70 @@
//! Tüm koleksiyonlarda ortak alanlar için yardımcılar (DATA_MODEL.md §1.1).
//!
//! Her kayıt şu alanları taşır:
//! `_id` (UUID v7), `household_id`, `created_at`, `updated_at`, `deleted_at`, `version`
#![allow(dead_code)] // Faz 1 – Adım 3 itibarıyla kullanılacak
use mongodb::bson::{DateTime, Document, Uuid, doc};
/// Yeni UUID v7 üretir. İlk 48 bit zaman damgası olduğu için
/// sonradan üretilen kimlik her zaman daha büyüktür (zamana göre sıralanabilir).
pub fn new_id() -> Uuid {
Uuid::from_bytes(uuid::Uuid::now_v7().into_bytes())
}
/// Şu anki zaman (UTC, BSON DateTime).
pub fn now() -> DateTime {
DateTime::now()
}
/// Yeni kayıt için ortak alanlar. Modele özgü alanlarla birleştirilir:
/// `let mut d = new_meta(hid); d.insert("name", "Market");`
pub fn new_meta(household_id: Uuid) -> Document {
let ts = now();
doc! {
"_id": new_id(),
"household_id": household_id,
"created_at": ts,
"updated_at": ts,
"deleted_at": null,
"version": 1_i32,
}
}
/// Hane kapsamlı, silinmemiş kayıtlar için temel filtre.
/// Tüm okuma sorguları bununla başlar → başka hanenin verisi asla dönmez.
pub fn scope(household_id: Uuid) -> Document {
doc! { "household_id": household_id, "deleted_at": null }
}
/// Güncellemelerde eklenecek ortak kısım: `updated_at` yenilenir, `version` +1.
pub fn touch() -> Document {
doc! {
"$set": { "updated_at": now() },
"$inc": { "version": 1_i32 },
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_id_is_v7_and_sortable() {
let a = uuid::Uuid::from_bytes(new_id().bytes());
std::thread::sleep(std::time::Duration::from_millis(2));
let b = uuid::Uuid::from_bytes(new_id().bytes());
assert_eq!(a.get_version_num(), 7);
assert!(b > a, "sonra üretilen UUID daha büyük olmalı");
}
#[test]
fn scope_always_filters_household_and_deleted() {
let hid = new_id();
let f = scope(hid);
assert_eq!(f.get("household_id"), Some(&hid.into()));
assert!(f.contains_key("deleted_at"));
}
}
+4
View File
@@ -0,0 +1,4 @@
//! Veritabanı modelleri. Her koleksiyonun yapısı, onu kullanan adımda eklenir.
//! Şema: `docs/DATA_MODEL.md`
pub mod common;