pub struct Api {
pub store: Store,
/* private fields */
}Fields§
§store: StoreImplementations§
Source§impl Api
impl Api
pub fn new(store: Store) -> Self
Sourcepub fn with_inline_driver(self, d: Driver) -> Self
pub fn with_inline_driver(self, d: Driver) -> Self
开启「提交后直接开推」。
§省掉的是那次抢占往返
老流程:提交方写完事务就返回,推进器再 lock_one_due 抢一次才能推。
那次抢占每笔事务都要付,在 Redis 上是一次 Lua 往返 —— 实测它就是
saga 落后 DTM 的主要原因(saga 只有一次客户端请求,摊不薄)。
新流程:建事务的那条写入里顺便把租约占在自己手上
(owner=自己、next_cron_time=现在+租约),写成功就等于抢到了,
直接推。零额外往返。
§跟 DTM 的差别:我们不阻塞提交
DTM 是在 submit 请求里同步把事务推完,客户端要一直等。这里是 spawn 出去推,提交立刻返回 —— 省掉往返的同时保住了提交延迟。
§代价
租约一占就是 lease 秒。如果进程在「写完」和「推完」之间挂了,
这笔要等租约到期才会被别的实例接手,而不是下一个 tick。
这跟「推进器抢到之后崩了」是同一种情形,不是新引入的风险。
Sourcepub async fn submit(
&self,
gid: &str,
trans_type: &str,
steps: &[SagaStep],
) -> Result<()>
pub async fn submit( &self, gid: &str, trans_type: &str, steps: &[SagaStep], ) -> Result<()>
提交。
重复提交同一个 gid 必须成功而不是报错 —— 客户端网络抖动重试时 返回错误会让它以为没受理,然后换个 gid 再来一次,就成了两笔。
Sourcepub async fn prepare(
&self,
gid: &str,
trans_type: &str,
actions: &[String],
query_prepared: &str,
grace_secs: Option<i64>,
) -> Result<()>
pub async fn prepare( &self, gid: &str, trans_type: &str, actions: &[String], query_prepared: &str, grace_secs: Option<i64>, ) -> Result<()>
第一阶段。msg 建 prepared 事务 + 正向分支;tcc / xa 只建空事务。
Sourcepub async fn register_branch(&self, r: &RegisterBranch) -> Result<()>
pub async fn register_branch(&self, r: &RegisterBranch) -> Result<()>
分支登记。必须先登记再做一阶段:反过来的话一阶段成功但登记失败, TC 就不知道有这个分支,回滚时不会处理它 —— TCC 是预留资源永久泄漏, XA 更糟,会留下一个永久持锁的 prepared 事务。
Sourcepub async fn retry(&self, gid: &str) -> Result<()>
pub async fn retry(&self, gid: &str) -> Result<()>
立刻重试:把下次调度时间提到现在,并清掉退避累积。
只是「排到队首」,不跳过任何安全检查 —— 分支该幂等还是要幂等。 终态事务不能重试(没意义,而且会让它重新变成活跃事务)。
pub async fn query(&self, gid: &str) -> Result<TransView>
pub async fn list_recent(&self, limit: i64) -> Vec<TransView>
Trait Implementations§
Auto Trait Implementations§
impl !RefUnwindSafe for Api
impl !UnwindSafe for Api
impl Freeze for Api
impl Send for Api
impl Sync for Api
impl Unpin for Api
impl UnsafeUnpin for Api
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
Mutably borrows from an owned value. Read more
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> ⓘ
Converts
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> ⓘ
Converts
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 moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
Wrap the input message
T in a tonic::Request