or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

backend-cores.mdcache-management.mdcore-decorator.mdglobal-configuration.mdindex.md

cache-management.mddocs/

0

# Cache Management

1

2

Cachier provides comprehensive cache management capabilities through methods attached to decorated functions. These methods allow you to control cache behavior, clear cached data, and pre-populate caches with known values.

3

4

## Capabilities

5

6

### Clear Cache

7

8

Remove all cached entries for a specific function:

9

10

```python { .api }

11

def clear_cache() -> None:

12

"""

13

Clear all cached entries for this function.

14

15

Removes all cached results from the function's cache storage.

16

The next call to the function will trigger a fresh calculation

17

regardless of any previously cached values.

18

"""

19

```

20

21

### Clear Being Calculated

22

23

Reset calculation state markers for concurrent access:

24

25

```python { .api }

26

def clear_being_calculated() -> None:

27

"""

28

Mark all entries in this cache as not being calculated.

29

30

Useful for resetting state after process crashes or when

31

calculation locks become stale. This allows other processes

32

to proceed with calculations that were previously marked

33

as being processed.

34

"""

35

```

36

37

### Cache Directory Path

38

39

Get the file system location where cache data is stored:

40

41

```python { .api }

42

def cache_dpath() -> Optional[str]:

43

"""

44

Return the path to the cache directory, if exists; None if not.

45

46

For file-based backends (pickle), returns the directory path

47

where cache files are stored. For other backends (memory,

48

mongo, redis, sql), returns None as they don't use filesystem

49

storage.

50

51

Returns:

52

str: Path to cache directory for file-based backends

53

None: For non-file backends or if directory doesn't exist

54

"""

55

```

56

57

### Precache Value

58

59

Add known values to the cache without function execution:

60

61

```python { .api }

62

def precache_value(*args, value_to_cache, **kwargs):

63

"""

64

Add an initial value to the cache.

65

66

Allows manual population of cache with known results, useful

67

for bootstrapping caches or providing fallback values.

68

69

Parameters:

70

- *args: Positional arguments that would be passed to function

71

- **kwargs: Keyword arguments that would be passed to function

72

- value_to_cache: The result value to store in cache

73

74

Returns:

75

The cached value (same as value_to_cache parameter)

76

"""

77

```

78

79

## Usage Examples

80

81

### Basic Cache Management

82

83

```python

84

from cachier import cachier

85

from datetime import timedelta

86

87

@cachier(stale_after=timedelta(hours=1))

88

def expensive_calculation(n, precision=2):

89

"""Simulate expensive computation."""

90

result = sum(i**precision for i in range(n))

91

return result

92

93

# Use the function normally

94

result1 = expensive_calculation(1000) # Computed and cached

95

result2 = expensive_calculation(1000) # Retrieved from cache

96

97

# Clear the cache when needed

98

expensive_calculation.clear_cache()

99

result3 = expensive_calculation(1000) # Computed again

100

101

# Check cache storage location

102

cache_path = expensive_calculation.cache_dpath()

103

if cache_path:

104

print(f"Cache files stored in: {cache_path}")

105

106

# Pre-populate cache with known values

107

expensive_calculation.precache_value(100, precision=2, value_to_cache=338350)

108

result4 = expensive_calculation(100, precision=2) # Uses precached value

109

```

110

111

### Concurrent Access Management

112

113

```python

114

import threading

115

from cachier import cachier

116

117

@cachier(backend='pickle', wait_for_calc_timeout=30)

118

def shared_computation(data_id):

119

"""Function that might be called concurrently."""

120

import time

121

time.sleep(5) # Simulate long computation

122

return f"processed_{data_id}"

123

124

def worker_thread(thread_id):

125

try:

126

result = shared_computation("shared_data")

127

print(f"Thread {thread_id}: {result}")

128

except Exception as e:

129

print(f"Thread {thread_id} failed: {e}")

130

131

# Start multiple threads

132

threads = []

133

for i in range(5):

134

t = threading.Thread(target=worker_thread, args=(i,))

135

threads.append(t)

136

t.start()

137

138

# If there's a process crash or hanging calculation

139

# Reset the calculation state

140

shared_computation.clear_being_calculated()

141

142

# Wait for all threads

143

for t in threads:

144

t.join()

145

```

146

147

### Cache Pre-population

148

149

```python

150

from cachier import cachier

151

import json

152

153

@cachier(backend='pickle')

154

def api_lookup(user_id, include_details=False):

155

"""Look up user data from API."""

156

# Simulate API call

157

import requests

158

url = f"https://api.example.com/users/{user_id}"

159

if include_details:

160

url += "?details=true"

161

return requests.get(url).json()

162

163

# Pre-populate cache with known test data

164

test_users = {

165

123: {"name": "Alice", "email": "alice@example.com"},

166

456: {"name": "Bob", "email": "bob@example.com"}

167

}

168

169

for user_id, user_data in test_users.items():

170

api_lookup.precache_value(user_id, value_to_cache=user_data)

171

api_lookup.precache_value(

172

user_id,

173

include_details=True,

174

value_to_cache={**user_data, "details": "full_profile"}

175

)

176

177

# Now these calls use precached data

178

alice = api_lookup(123) # Uses precached data

179

bob_detailed = api_lookup(456, include_details=True) # Uses precached data

180

```

181

182

### Selective Cache Clearing

183

184

```python

185

from cachier import cachier

186

import os

187

188

@cachier(backend='pickle', separate_files=True)

189

def process_file(file_path, options=None):

190

"""Process a file with caching."""

191

with open(file_path, 'r') as f:

192

content = f.read()

193

194

if options and options.get('uppercase'):

195

content = content.upper()

196

197

return {"content": content, "size": len(content)}

198

199

# Process several files

200

result1 = process_file("/path/to/file1.txt")

201

result2 = process_file("/path/to/file2.txt", {"uppercase": True})

202

result3 = process_file("/path/to/file3.txt")

203

204

# Clear all cached results

205

process_file.clear_cache()

206

207

# With separate_files=True, you can also manually remove

208

# specific cache files if needed

209

cache_dir = process_file.cache_dpath()

210

if cache_dir and os.path.exists(cache_dir):

211

cache_files = os.listdir(cache_dir)

212

print(f"Cache files: {cache_files}")

213

```

214

215

### Error Recovery

216

217

```python

218

from cachier import cachier

219

import logging

220

221

logger = logging.getLogger(__name__)

222

223

@cachier(backend='mongo', wait_for_calc_timeout=60)

224

def distributed_task(task_id):

225

"""Task that runs on multiple machines."""

226

# Long-running distributed computation

227

return perform_distributed_analysis(task_id)

228

229

def recover_from_crash():

230

"""Recovery procedure after system crash."""

231

try:

232

# Clear any stale calculation locks

233

distributed_task.clear_being_calculated()

234

logger.info("Cleared stale calculation locks")

235

236

# Optionally clear cache if data might be corrupted

237

# distributed_task.clear_cache()

238

# logger.info("Cleared potentially corrupted cache")

239

240

except Exception as e:

241

logger.error(f"Recovery failed: {e}")

242

243

# Call during application startup after crash

244

recover_from_crash()

245

```

246

247

### Cache Inspection and Maintenance

248

249

```python

250

from cachier import cachier

251

import os

252

import json

253

from datetime import datetime

254

255

@cachier(

256

backend='pickle',

257

separate_files=True,

258

cleanup_stale=True,

259

cleanup_interval=timedelta(hours=1)

260

)

261

def monitored_function(param):

262

"""Function with cache monitoring."""

263

return complex_computation(param)

264

265

def inspect_cache():

266

"""Inspect cache state and perform maintenance."""

267

cache_dir = monitored_function.cache_dpath()

268

269

if not cache_dir or not os.path.exists(cache_dir):

270

print("No cache directory found")

271

return

272

273

cache_files = os.listdir(cache_dir)

274

print(f"Found {len(cache_files)} cache files")

275

276

total_size = 0

277

for filename in cache_files:

278

file_path = os.path.join(cache_dir, filename)

279

if os.path.isfile(file_path):

280

size = os.path.getsize(file_path)

281

total_size += size

282

mtime = datetime.fromtimestamp(os.path.getmtime(file_path))

283

print(f" {filename}: {size} bytes, modified {mtime}")

284

285

print(f"Total cache size: {total_size} bytes")

286

287

# Clear cache if it's too large

288

if total_size > 1024 * 1024 * 100: # 100MB

289

print("Cache size exceeds limit, clearing...")

290

monitored_function.clear_cache()

291

292

# Run periodic maintenance

293

inspect_cache()

294

```

295

296

## Method Availability

297

298

These cache management methods are automatically attached to all functions decorated with `@cachier()`:

299

300

- **Available on all decorated functions**: `clear_cache()`, `clear_being_calculated()`, `precache_value()`

301

- **Available only on file-based backends**: `cache_dpath()` returns a path

302

- **Returns None for non-file backends**: `cache_dpath()` for memory, mongo, redis, sql backends

303

304

The methods provide a consistent interface regardless of the backend used, allowing you to write cache management code that works across different storage systems.