fix(health): 设备数据管线 Phase 1 缺陷修复 + AI 产品策略讨论
- device_readings 批量插入添加 ON CONFLICT 去重唯一索引 - 小程序 BLEManager 增加离线缓存(Storage 持久化 + 启动重传) - 新增 device_readings 90 天数据保留清理定时任务 - 小米手环适配器增加 RACP 历史心率读取支持 - SSE 告警按医生过滤已确认实现(patient_doctor_relation) - 新增 AI 产品策略与设备数据医院场景讨论记录
This commit is contained in:
@@ -223,13 +223,26 @@ async fn batch_insert_readings(
|
||||
})
|
||||
.collect();
|
||||
|
||||
let count = models.len() as u64;
|
||||
let total = models.len() as u64;
|
||||
device_readings::Entity::insert_many(models)
|
||||
.on_conflict(
|
||||
sea_orm::sea_query::OnConflict::columns([
|
||||
device_readings::Column::TenantId,
|
||||
device_readings::Column::PatientId,
|
||||
device_readings::Column::DeviceId,
|
||||
device_readings::Column::Metric,
|
||||
device_readings::Column::MeasuredAt,
|
||||
])
|
||||
.do_nothing()
|
||||
.to_owned(),
|
||||
)
|
||||
.exec(db)
|
||||
.await
|
||||
.map_err(|e| HealthError::DbError(e.to_string()))?;
|
||||
|
||||
Ok(count)
|
||||
// ON CONFLICT DO NOTHING 不返回精确插入数,返回提交总数
|
||||
// 调用方通过 BatchResult.duplicates 字段语义不变
|
||||
Ok(total)
|
||||
}
|
||||
|
||||
async fn upsert_hourly_aggregates(
|
||||
@@ -532,3 +545,33 @@ async fn sync_bp_glucose_to_vital_signs(
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 清理超过 90 天的设备原始数据,分批删除避免长事务
|
||||
pub async fn cleanup_stale_readings(
|
||||
db: &DatabaseConnection,
|
||||
) -> HealthResult<u64> {
|
||||
let cutoff = Utc::now() - chrono::Duration::days(90);
|
||||
let batch_size = 1000i64;
|
||||
let mut total_deleted = 0u64;
|
||||
|
||||
loop {
|
||||
let result = db.execute(sea_orm::Statement::from_sql_and_values(
|
||||
sea_orm::DatabaseBackend::Postgres,
|
||||
"DELETE FROM device_readings WHERE measured_at < $1 AND id IN (SELECT id FROM device_readings WHERE measured_at < $1 LIMIT $2)",
|
||||
[cutoff.into(), (batch_size as i32).into()],
|
||||
)).await;
|
||||
|
||||
match result {
|
||||
Ok(res) => {
|
||||
let rows = res.rows_affected();
|
||||
total_deleted += rows;
|
||||
if rows < batch_size as u64 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(HealthError::DbError(e.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(total_deleted)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user