Skip to main content

WalLock

Struct WalLock 

Source
pub struct WalLock { /* private fields */ }
Expand description

单写者锁:持锁期间同一份 WAL 只允许这一个写进程存在(fail-closed)。

为什么必须有:闸的账本、nonce 登记、撤销集合都在内存里,WAL 只在启动时 回放一次。两个都已活着的进程共写一份 WAL,各自内存账本只知道自己花了几笔—— 实测(本仓 tests/single_writer.rs,修复前)两进程各放行 700 分、委托 cap 1000 分,合计 1400 分:预算硬上限失效,且 WAL 出现两行同一 id 的注册, 下次回放对账必炸。.mcp.json.trae/mcp.json 指向同一份默认 WAL, 两个平台并挂就是真实场景。

机制(零依赖、跨平台):create_new(O_EXCL)原子创建锁文件——两个进程 同时抢,恰好一个成功;内容 = 持锁进程 PID + WAL 路径,供拒启方报错指认。 锁随 Drop for WalLock 释放(正常退出/panic 展开都会走到)。

已知权衡(记录于决策记录):持锁进程被 kill -9 会留下孤儿锁, 下一个进程拒启,按错误信息确认无活进程后手动删除锁文件即可恢复(默认 WAL 在 target/ 下,cargo clean 亦可)。刻意不做「自动判死」:std 没有跨平台进程 存活检查,臆造判活逻辑比让所有者手删一行文件危险得多——审计闸宁可拒启,不可 带病放行。

语义边界:锁只挡写进程,不挡读者——回放/审计读取走只读打开,服务运行 期间照常可用(见 tests/single_writer.rs::replay_works_while_writer_holds_lock)。

Implementations§

Source§

impl WalLock

Source

pub fn acquire(wal_path: impl AsRef<Path>) -> Result<Self, CoreError>

拿单写者锁;被占 → CoreError::WalLocked

Trait Implementations§

Source§

impl Debug for WalLock

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Drop for WalLock

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.