pub struct SqlStore { /* private fields */ }Implementations§
Source§impl SqlStore
impl SqlStore
Sourcepub async fn open(url: &str) -> Result<Self>
pub async fn open(url: &str) -> Result<Self>
url 可以是:
sqlite:dtmrs.db/sqlite::memory:postgres://user:pass@host:5432/db
pub async fn migrate(&self) -> Result<()>
pub fn backend(&self) -> Backend
pub fn pool(&self) -> &AnyPool
Sourcepub async fn create_global(
&self,
g: &GlobalRow,
branches: &[BranchRow],
) -> Result<bool>
pub async fn create_global( &self, g: &GlobalRow, branches: &[BranchRow], ) -> Result<bool>
建全局事务 + 所有分支,一个事务里做完。
返回 false 表示 gid 已存在 —— 这是幂等提交,不是错误:
客户端重试提交时必须拿到“已受理“而不是报错。
pub async fn create_token( &self, hash: &str, name: &str, secret: &str, ) -> Result<()>
pub async fn list_tokens(&self) -> Result<Vec<TokenRow>>
Sourcepub async fn revoke_token(&self, hash: &str) -> Result<bool>
pub async fn revoke_token(&self, hash: &str) -> Result<bool>
作废。不删行 —— 留着才能在管理台看到「这个 token 什么时候被谁作废的」
Sourcepub async fn active_token_hashes(&self) -> Result<Vec<String>>
pub async fn active_token_hashes(&self) -> Result<Vec<String>>
当前有效的令牌哈希。认证的热路径不查这个 —— 上层按 TTL 缓存,
见 dtmrs_server::auth
Sourcepub async fn touch_token(&self, hash: &str, ip: &str) -> Result<()>
pub async fn touch_token(&self, hash: &str, ip: &str) -> Result<()>
记一次使用。尽力而为:失败只吞掉不影响请求 —— 统计信息不值得让一次正常的业务调用失败
pub async fn get_global(&self, gid: &str) -> Result<Option<GlobalRow>>
pub async fn list_branches(&self, gid: &str) -> Result<Vec<BranchRow>>
Sourcepub async fn set_global_status(
&self,
gid: &str,
status: GlobalStatus,
_trans_type: TransType,
reason: &str,
) -> Result<()>
pub async fn set_global_status( &self, gid: &str, status: GlobalStatus, _trans_type: TransType, reason: &str, ) -> Result<()>
落全局状态。
trans_type 这一层用不上(UPDATE 不需要它),但 Redis 后端靠它把
「落终态」这条热路径从 Lua 脚本降级成一次 MULTI —— 两边签名要一致
Sourcepub async fn set_branch_result(
&self,
gid: &str,
branch_id: &str,
op: BranchOp,
status: BranchStatus,
payload: &str,
) -> Result<()>
pub async fn set_branch_result( &self, gid: &str, branch_id: &str, op: BranchOp, status: BranchStatus, payload: &str, ) -> Result<()>
落一个分支的状态和结果数据。
workflow 模式的重放靠这个:函数崩溃后会从头再跑一遍,已完成的分支
不重新执行,而是把上次存的 payload 原样还给它。所以这个值必须跟
「分支已成功」在同一条 UPDATE 里落盘 —— 分两步写的话,中间崩了
就会出现「标了成功但结果丢了」,重放时拿不到返回值。
pub async fn set_branch_status( &self, gid: &str, branch_id: &str, op: BranchOp, status: BranchStatus, ) -> Result<()>
Sourcepub async fn lock_one_due(
&self,
owner: &str,
lease: i64,
) -> Result<Option<GlobalRow>>
pub async fn lock_one_due( &self, owner: &str, lease: i64, ) -> Result<Option<GlobalRow>>
抢一个到期的待办事务,抢占式更新,原子的。
多个 TC 实例同时跑也不会重复推进同一个事务:谁的 UPDATE 生效谁持有租约。
持租约的实例崩了,next_cron_time 到期后别的实例接手 —— 这就是崩溃恢复。
Sourcepub async fn submit_prepared(
&self,
gid: &str,
owner: &str,
next_cron_time: i64,
) -> Result<SubmitOutcome>
pub async fn submit_prepared( &self, gid: &str, owner: &str, next_cron_time: i64, ) -> Result<SubmitOutcome>
把停在 prepared 的事务推成 submitted,并立刻排进调度队列。
一次调用做完原来三次的活(get_global + set_global_status +
schedule_now)。Redis 后端上这是一个 Lua 脚本,11 条命令降到 3 条 ——
那边是单线程 CPU 瓶颈,命令数直接决定吞吐。
owner / next_cron_time 让提交方顺便把租约占下来:传自己的
owner 和「现在 + 租约」,这一条 UPDATE 之后事务就归调用方推了,
不用再走一次抢占。不想占就传空 owner 和 now()。
Sourcepub async fn schedule_now(&self, gid: &str) -> Result<()>
pub async fn schedule_now(&self, gid: &str) -> Result<()>
让某个事务立刻可被调度(提交/中止之后叫一下,不用等 cron 周期)
Sourcepub async fn register_branch(
&self,
gid: &str,
branch_id: &str,
ops: &[(BranchOp, String)],
) -> Result<()>
pub async fn register_branch( &self, gid: &str, branch_id: &str, ops: &[(BranchOp, String)], ) -> Result<()>
TCC 的 try 阶段:客户端在调 try 之前先来登记这个分支的 confirm/cancel。
必须先登记再调 try。反过来的话:try 成功了但登记失败, TC 就不知道有这个分支,回滚时不会 cancel 它 —— 资源永久泄漏。
冲突时忽略,所以重复登记是幂等的(客户端重试很常见)。
pub async fn list_recent(&self, limit: i64) -> Result<Vec<GlobalRow>>
Trait Implementations§
Auto Trait Implementations§
impl !RefUnwindSafe for SqlStore
impl !UnwindSafe for SqlStore
impl Freeze for SqlStore
impl Send for SqlStore
impl Sync for SqlStore
impl Unpin for SqlStore
impl UnsafeUnpin for SqlStore
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more