python
from collections import deque
nodes = ["A", "B"]
balances = {
"A": 1000,
"B": 500,
}
channels = {
("A", "B"): deque(),
("B", "A"): deque(),
}
local_snapshot = {}
channel_snapshot = {}
recording = set()
def send(src, dst, kind, amount=0):
channels[(src, dst)].append(
(kind, amount)
)
def record_local(node, first_marker_channel=None):
"""
保存节点的本地快照。
first_marker_channel:
导致该节点第一次开始快照的入站通道。
这条通道的快照状态为空。
"""
local_snapshot[node] = balances[node]
for channel in channels:
src, dst = channel
if dst != node:
continue
channel_snapshot[channel] = []
if channel != first_marker_channel:
recording.add(channel)
for channel in channels:
src, dst = channel
if src == node:
send(src, dst, "MARKER")
def receive(src, dst):
channel = (src, dst)
kind, amount = channels[channel].popleft()
if kind == "MARKER":
if dst not in local_snapshot:
record_local(
dst,
first_marker_channel=channel,
)
else:
recording.discard(channel)
elif kind == "TRANSFER":
if channel in recording:
channel_snapshot[channel].append(amount)
balances[dst] += amount
python
balances["A"] -= 100
send("A", "B", "TRANSFER", 100)
record_local("B")
receive("B", "A")
receive("A", "B")
receive("A", "B")
text
{'B': 500, 'A': 900}
{('A', 'B'): [100], ('B', 'A'): []}
1500
{'A': 900, 'B': 600}