The before code shows independent updates that can fail partially. The after code introduces a coordinator that asks each service to prepare, then commits all or rolls back all, ensuring atomicity.
### Before (no coordination, risk of partial failure)
class ServiceA:
def update(self):
# update local DB
pass
class ServiceB:
def update(self):
# update local DB
pass
# Caller calls both updates independently
service_a = ServiceA()
service_b = ServiceB()
service_a.update()
service_b.update() # if this fails, data is inconsistent
### After (Two-phase commit coordinator)
class Coordinator:
def __init__(self, services):
self.services = services
def two_phase_commit(self):
# Phase 1: prepare
for s in self.services:
if not s.prepare():
self.rollback_all()
return False
# Phase 2: commit
for s in self.services:
s.commit()
return True
def rollback_all(self):
for s in self.services:
s.rollback()
class ServiceA:
def prepare(self):
# check if update possible
return True
def commit(self):
# apply update
pass
def rollback(self):
# undo changes
pass
class ServiceB:
def prepare(self):
return True
def commit(self):
pass
def rollback(self):
pass
services = [ServiceA(), ServiceB()]
coordinator = Coordinator(services)
coordinator.two_phase_commit()