or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async.mdcircuit-breaker.mdindex.mdlisteners.mdstorage.md

storage.mddocs/

0

# Storage Backends

1

2

PyBreaker supports different storage backends for persisting circuit breaker state. This enables circuit breakers to maintain state across application restarts and coordinate state in distributed systems.

3

4

## Capabilities

5

6

### Memory Storage

7

8

In-memory storage for single-process applications where circuit state doesn't need to persist across restarts.

9

10

```python { .api }

11

class CircuitMemoryStorage:

12

def __init__(self, state: str):

13

"""

14

Create a new in-memory storage instance.

15

16

Args:

17

state (str): Initial circuit state ('open', 'closed', 'half-open')

18

"""

19

20

@property

21

def state(self) -> str:

22

"""Current circuit breaker state."""

23

24

@state.setter

25

def state(self, state: str) -> None:

26

"""Set the current circuit breaker state."""

27

28

@property

29

def counter(self) -> int:

30

"""Current failure counter value."""

31

32

@property

33

def success_counter(self) -> int:

34

"""Current success counter value."""

35

36

@property

37

def opened_at(self) -> datetime | None:

38

"""Datetime when circuit was last opened."""

39

40

@opened_at.setter

41

def opened_at(self, datetime: datetime) -> None:

42

"""Set when circuit was opened."""

43

44

def increment_counter(self) -> None:

45

"""Increment the failure counter by one."""

46

47

def reset_counter(self) -> None:

48

"""Reset the failure counter to zero."""

49

50

def increment_success_counter(self) -> None:

51

"""Increment the success counter by one."""

52

53

def reset_success_counter(self) -> None:

54

"""Reset the success counter to zero."""

55

```

56

57

### Redis Storage

58

59

Redis-backed storage for distributed applications where circuit state needs to be shared across multiple processes or servers.

60

61

```python { .api }

62

class CircuitRedisStorage:

63

def __init__(self,

64

state: str,

65

redis_object: Redis,

66

namespace: str | None = None,

67

fallback_circuit_state: str = "closed",

68

cluster_mode: bool = False):

69

"""

70

Create a new Redis storage instance.

71

72

Args:

73

state (str): Initial circuit state

74

redis_object (Redis): Redis client instance (e.g., redis.Redis())

75

namespace (str | None): Optional namespace for Redis keys

76

fallback_circuit_state (str): State to use when Redis is unavailable

77

cluster_mode (bool): Enable Redis cluster mode support

78

79

Note:

80

Requires 'redis' package to be installed.

81

Do not use decode_responses=True in Redis client.

82

Check pybreaker.HAS_REDIS_SUPPORT to verify availability.

83

"""

84

85

@property

86

def state(self) -> str:

87

"""

88

Current circuit breaker state from Redis.

89

Falls back to fallback_circuit_state on Redis errors.

90

"""

91

92

@state.setter

93

def state(self, state: str) -> None:

94

"""Set the current circuit breaker state in Redis."""

95

96

@property

97

def counter(self) -> int:

98

"""Current failure counter value from Redis."""

99

100

@property

101

def success_counter(self) -> int:

102

"""Current success counter value from Redis."""

103

104

@property

105

def opened_at(self) -> datetime | None:

106

"""Datetime when circuit was last opened, from Redis."""

107

108

@opened_at.setter

109

def opened_at(self, datetime: datetime) -> None:

110

"""Atomically set when circuit was opened in Redis."""

111

112

def increment_counter(self) -> None:

113

"""Increment the failure counter in Redis."""

114

115

def reset_counter(self) -> None:

116

"""Reset the failure counter to zero in Redis."""

117

118

def increment_success_counter(self) -> None:

119

"""Increment the success counter in Redis."""

120

121

def reset_success_counter(self) -> None:

122

"""Reset the success counter to zero in Redis."""

123

```

124

125

### Storage Base Class

126

127

Abstract base class defining the storage interface for custom storage implementations. All concrete storage classes must inherit from this class and implement the abstract methods.

128

129

```python { .api }

130

class CircuitBreakerStorage:

131

def __init__(self, name: str) -> None:

132

"""

133

Create a new storage instance.

134

135

Args:

136

name (str): Human-friendly name for this storage type

137

"""

138

139

@property

140

def name(self) -> str:

141

"""Human friendly name that identifies this storage type."""

142

143

@property

144

def state(self) -> str:

145

"""Override this method to retrieve the current circuit breaker state."""

146

147

@state.setter

148

def state(self, state: str) -> None:

149

"""Override this method to set the current circuit breaker state."""

150

151

def increment_counter(self) -> None:

152

"""Override this method to increase the failure counter by one."""

153

154

def reset_counter(self) -> None:

155

"""Override this method to set the failure counter to zero."""

156

157

def increment_success_counter(self) -> None:

158

"""Override this method to increase the success counter by one."""

159

160

def reset_success_counter(self) -> None:

161

"""Override this method to set the success counter to zero."""

162

163

@property

164

def counter(self) -> int:

165

"""Override this method to retrieve the current failure counter value."""

166

167

@property

168

def success_counter(self) -> int:

169

"""Override this method to retrieve the current success counter value."""

170

171

@property

172

def opened_at(self) -> datetime | None:

173

"""Override this method to retrieve when the circuit was opened."""

174

175

@opened_at.setter

176

def opened_at(self, datetime: datetime) -> None:

177

"""Override this method to set when the circuit was opened."""

178

```

179

180

## Usage Examples

181

182

### Memory Storage (Default)

183

184

```python

185

import pybreaker

186

187

# Memory storage is used by default

188

breaker = pybreaker.CircuitBreaker(fail_max=5, reset_timeout=60)

189

190

# Explicitly specify memory storage

191

storage = pybreaker.CircuitMemoryStorage(state=pybreaker.STATE_CLOSED)

192

breaker = pybreaker.CircuitBreaker(state_storage=storage)

193

```

194

195

### Redis Storage for Distributed Systems

196

197

```python

198

import pybreaker

199

import redis

200

201

# Create Redis client

202

redis_client = redis.Redis(host='localhost', port=6379, db=0)

203

204

# Create Redis storage

205

storage = pybreaker.CircuitRedisStorage(

206

state=pybreaker.STATE_CLOSED,

207

redis_object=redis_client,

208

namespace="myapp", # Optional namespace for keys

209

fallback_circuit_state=pybreaker.STATE_CLOSED

210

)

211

212

# Create circuit breaker with Redis storage

213

breaker = pybreaker.CircuitBreaker(

214

fail_max=5,

215

reset_timeout=60,

216

state_storage=storage,

217

name="user_service"

218

)

219

```

220

221

### Redis Storage with Django

222

223

```python

224

import pybreaker

225

from django_redis import get_redis_connection

226

227

# Use existing Django Redis connection

228

redis_client = get_redis_connection('default')

229

230

storage = pybreaker.CircuitRedisStorage(

231

state=pybreaker.STATE_CLOSED,

232

redis_object=redis_client,

233

namespace="circuit_breakers"

234

)

235

236

breaker = pybreaker.CircuitBreaker(state_storage=storage)

237

```

238

239

### Multiple Circuit Breakers with Redis

240

241

```python

242

import pybreaker

243

import redis

244

245

redis_client = redis.Redis(host='localhost', port=6379, db=0)

246

247

# Each service gets its own namespace

248

user_storage = pybreaker.CircuitRedisStorage(

249

state=pybreaker.STATE_CLOSED,

250

redis_object=redis_client,

251

namespace="user_service"

252

)

253

254

payment_storage = pybreaker.CircuitRedisStorage(

255

state=pybreaker.STATE_CLOSED,

256

redis_object=redis_client,

257

namespace="payment_service"

258

)

259

260

user_breaker = pybreaker.CircuitBreaker(state_storage=user_storage)

261

payment_breaker = pybreaker.CircuitBreaker(state_storage=payment_storage)

262

```

263

264

### Redis Cluster Mode

265

266

```python

267

import pybreaker

268

import redis

269

270

# For Redis cluster deployments

271

redis_client = redis.Redis(host='cluster-endpoint', port=6379)

272

273

storage = pybreaker.CircuitRedisStorage(

274

state=pybreaker.STATE_CLOSED,

275

redis_object=redis_client,

276

cluster_mode=True # Enable cluster mode

277

)

278

279

breaker = pybreaker.CircuitBreaker(state_storage=storage)

280

```

281

282

### Custom Storage Implementation

283

284

```python

285

import pybreaker

286

import sqlite3

287

from datetime import datetime

288

289

class SQLiteStorage(pybreaker.CircuitBreakerStorage):

290

def __init__(self, db_path, circuit_name):

291

super().__init__("sqlite")

292

self.db_path = db_path

293

self.circuit_name = circuit_name

294

self._init_db()

295

296

def _init_db(self):

297

# Initialize SQLite database and tables

298

pass

299

300

@property

301

def state(self):

302

# Implement state retrieval from SQLite

303

pass

304

305

@state.setter

306

def state(self, state):

307

# Implement state storage to SQLite

308

pass

309

310

# Implement other required methods...

311

312

# Use custom storage

313

storage = SQLiteStorage("/path/to/circuit.db", "user_service")

314

breaker = pybreaker.CircuitBreaker(state_storage=storage)

315

```