123 lines
3.7 KiB
Rust
123 lines
3.7 KiB
Rust
use crate::*;
|
|
|
|
const AUTH_STORE_SNAPSHOT_ID: &str = "default";
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
|
pub struct AuthStoreSnapshotRecord {
|
|
pub snapshot_json: Option<String>,
|
|
pub updated_at_micros: Option<i64>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
|
pub struct AuthStoreSnapshotUpsertInput {
|
|
pub snapshot_json: String,
|
|
pub updated_at_micros: i64,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
|
pub struct AuthStoreSnapshotProcedureResult {
|
|
pub ok: bool,
|
|
pub record: Option<AuthStoreSnapshotRecord>,
|
|
pub error_message: Option<String>,
|
|
}
|
|
|
|
#[spacetimedb::table(accessor = auth_store_snapshot)]
|
|
pub struct AuthStoreSnapshot {
|
|
#[primary_key]
|
|
pub(crate) snapshot_id: String,
|
|
pub(crate) snapshot_json: String,
|
|
pub(crate) updated_at: Timestamp,
|
|
}
|
|
|
|
// Axum 启动恢复认证状态时读取当前快照;记录不存在代表尚未产生登录态。
|
|
#[spacetimedb::procedure]
|
|
pub fn get_auth_store_snapshot(ctx: &mut ProcedureContext) -> AuthStoreSnapshotProcedureResult {
|
|
match ctx.try_with_tx(|tx| get_auth_store_snapshot_tx(tx)) {
|
|
Ok(record) => AuthStoreSnapshotProcedureResult {
|
|
ok: true,
|
|
record: Some(record),
|
|
error_message: None,
|
|
},
|
|
Err(message) => AuthStoreSnapshotProcedureResult {
|
|
ok: false,
|
|
record: None,
|
|
error_message: Some(message),
|
|
},
|
|
}
|
|
}
|
|
|
|
// Axum 每次鉴权仓储变更后覆盖写入整份快照,后续拆表阶段再替换为细粒度 reducer。
|
|
#[spacetimedb::procedure]
|
|
pub fn upsert_auth_store_snapshot(
|
|
ctx: &mut ProcedureContext,
|
|
input: AuthStoreSnapshotUpsertInput,
|
|
) -> AuthStoreSnapshotProcedureResult {
|
|
match ctx.try_with_tx(|tx| upsert_auth_store_snapshot_tx(tx, input.clone())) {
|
|
Ok(record) => AuthStoreSnapshotProcedureResult {
|
|
ok: true,
|
|
record: Some(record),
|
|
error_message: None,
|
|
},
|
|
Err(message) => AuthStoreSnapshotProcedureResult {
|
|
ok: false,
|
|
record: None,
|
|
error_message: Some(message),
|
|
},
|
|
}
|
|
}
|
|
|
|
fn get_auth_store_snapshot_tx(ctx: &ReducerContext) -> Result<AuthStoreSnapshotRecord, String> {
|
|
Ok(
|
|
match ctx
|
|
.db
|
|
.auth_store_snapshot()
|
|
.snapshot_id()
|
|
.find(&AUTH_STORE_SNAPSHOT_ID.to_string())
|
|
{
|
|
Some(row) => AuthStoreSnapshotRecord {
|
|
snapshot_json: Some(row.snapshot_json),
|
|
updated_at_micros: Some(row.updated_at.to_micros_since_unix_epoch()),
|
|
},
|
|
None => AuthStoreSnapshotRecord {
|
|
snapshot_json: None,
|
|
updated_at_micros: None,
|
|
},
|
|
},
|
|
)
|
|
}
|
|
|
|
fn upsert_auth_store_snapshot_tx(
|
|
ctx: &ReducerContext,
|
|
input: AuthStoreSnapshotUpsertInput,
|
|
) -> Result<AuthStoreSnapshotRecord, String> {
|
|
let snapshot_json = input.snapshot_json.trim().to_string();
|
|
if snapshot_json.is_empty() {
|
|
return Err("认证快照 JSON 不能为空".to_string());
|
|
}
|
|
let updated_at = Timestamp::from_micros_since_unix_epoch(input.updated_at_micros);
|
|
|
|
if ctx
|
|
.db
|
|
.auth_store_snapshot()
|
|
.snapshot_id()
|
|
.find(&AUTH_STORE_SNAPSHOT_ID.to_string())
|
|
.is_some()
|
|
{
|
|
ctx.db
|
|
.auth_store_snapshot()
|
|
.snapshot_id()
|
|
.delete(&AUTH_STORE_SNAPSHOT_ID.to_string());
|
|
}
|
|
|
|
ctx.db.auth_store_snapshot().insert(AuthStoreSnapshot {
|
|
snapshot_id: AUTH_STORE_SNAPSHOT_ID.to_string(),
|
|
snapshot_json: snapshot_json.clone(),
|
|
updated_at,
|
|
});
|
|
|
|
Ok(AuthStoreSnapshotRecord {
|
|
snapshot_json: Some(snapshot_json),
|
|
updated_at_micros: Some(input.updated_at_micros),
|
|
})
|
|
}
|