or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

browser-integration.mdcache-management.mdclient-management.mdhydration.mdindex.mdinfinite-queries.mdmutations.mdquery-observers.mdquery-operations.mdutilities.md

cache-management.mddocs/

0

# Cache Management

1

2

Low-level cache operations for direct query and mutation cache manipulation with events, filtering, batch operations, and advanced cache strategies.

3

4

## Capabilities

5

6

### QueryCache

7

8

Low-level cache for managing query instances and their lifecycle.

9

10

```typescript { .api }

11

/**

12

* Cache for managing Query instances

13

* Provides direct access to query storage and lifecycle management

14

*/

15

class QueryCache {

16

constructor(config?: QueryCacheConfig);

17

18

/**

19

* Build or retrieve a query from the cache

20

* Creates new query if it doesn't exist, otherwise returns existing

21

* @param client - QueryClient instance

22

* @param options - Query options

23

* @param state - Optional initial state

24

* @returns Query instance

25

*/

26

build<T>(client: QueryClient, options: QueryOptions<T>, state?: QueryState<T>): Query<T>;

27

28

/**

29

* Add a query to the cache

30

* @param query - Query instance to add

31

*/

32

add(query: Query): void;

33

34

/**

35

* Remove a query from the cache

36

* @param query - Query instance to remove

37

*/

38

remove(query: Query): void;

39

40

/**

41

* Clear all queries from the cache

42

*/

43

clear(): void;

44

45

/**

46

* Get a query by its hash

47

* @param queryHash - The query hash to look up

48

* @returns Query instance or undefined if not found

49

*/

50

get<T>(queryHash: string): Query<T> | undefined;

51

52

/**

53

* Get all queries in the cache

54

* @returns Array of all Query instances

55

*/

56

getAll(): Array<Query>;

57

58

/**

59

* Find the first query matching the filters

60

* @param filters - Query filters to match against

61

* @returns First matching Query instance or undefined

62

*/

63

find<T>(filters: QueryFilters): Query<T> | undefined;

64

65

/**

66

* Find all queries matching the filters

67

* @param filters - Query filters to match against

68

* @returns Array of matching Query instances

69

*/

70

findAll(filters?: QueryFilters): Array<Query>;

71

72

/**

73

* Subscribe to cache events

74

* @param callback - Callback function for cache events

75

* @returns Unsubscribe function

76

*/

77

subscribe(callback: (event: QueryCacheNotifyEvent) => void): () => void;

78

79

/**

80

* Notify cache listeners of an event

81

* @param event - Cache event to broadcast

82

*/

83

notify(event: QueryCacheNotifyEvent): void;

84

85

/**

86

* Handle window focus event

87

* Triggers refetch for queries configured to refetch on focus

88

*/

89

onFocus(): void;

90

91

/**

92

* Handle online event

93

* Triggers refetch for queries configured to refetch on reconnect

94

*/

95

onOnline(): void;

96

}

97

98

interface QueryCacheConfig {

99

/**

100

* Called when any query encounters an error

101

* @param error - The error that occurred

102

* @param query - The query that failed

103

*/

104

onError?: (error: Error, query: Query) => void;

105

106

/**

107

* Called when any query succeeds

108

* @param data - The data returned by the query

109

* @param query - The query that succeeded

110

*/

111

onSuccess?: (data: unknown, query: Query) => void;

112

113

/**

114

* Called when any query settles (success or error)

115

* @param data - The data returned (undefined if error)

116

* @param error - The error that occurred (null if success)

117

* @param query - The query that settled

118

*/

119

onSettled?: (data: unknown | undefined, error: Error | null, query: Query) => void;

120

}

121

```

122

123

**Usage Examples:**

124

125

```typescript

126

import { QueryCache, QueryClient } from "@tanstack/query-core";

127

128

// Create cache with event handlers

129

const queryCache = new QueryCache({

130

onError: (error, query) => {

131

console.log(`Query failed:`, query.queryKey, error);

132

133

// Log errors to monitoring service

134

errorReporting.captureException(error, {

135

tags: { queryKey: JSON.stringify(query.queryKey) },

136

});

137

},

138

onSuccess: (data, query) => {

139

console.log(`Query succeeded:`, query.queryKey);

140

},

141

onSettled: (data, error, query) => {

142

console.log(`Query settled:`, query.queryKey, { data, error });

143

},

144

});

145

146

const queryClient = new QueryClient({ queryCache });

147

148

// Subscribe to cache events

149

const unsubscribe = queryCache.subscribe((event) => {

150

switch (event.type) {

151

case 'added':

152

console.log('Query added:', event.query.queryKey);

153

break;

154

case 'removed':

155

console.log('Query removed:', event.query.queryKey);

156

break;

157

case 'updated':

158

console.log('Query updated:', event.query.queryKey, event.action);

159

break;

160

case 'observerAdded':

161

console.log('Observer added to query:', event.query.queryKey);

162

break;

163

case 'observerRemoved':

164

console.log('Observer removed from query:', event.query.queryKey);

165

break;

166

}

167

});

168

169

// Find queries by filters

170

const staleQueries = queryCache.findAll({ stale: true });

171

console.log(`Found ${staleQueries.length} stale queries`);

172

173

const userQueries = queryCache.findAll({

174

queryKey: ['user'],

175

exact: false, // Partial match

176

});

177

178

// Get specific query

179

const userQuery = queryCache.find({ queryKey: ['user', 123], exact: true });

180

if (userQuery) {

181

console.log('User query state:', userQuery.state);

182

}

183

184

// Clear cache

185

queryCache.clear();

186

187

// Cleanup

188

unsubscribe();

189

```

190

191

### MutationCache

192

193

Low-level cache for managing mutation instances and their execution.

194

195

```typescript { .api }

196

/**

197

* Cache for managing Mutation instances

198

* Handles mutation storage, scoping, and execution coordination

199

*/

200

class MutationCache {

201

constructor(config?: MutationCacheConfig);

202

203

/**

204

* Build or retrieve a mutation from the cache

205

* @param client - QueryClient instance

206

* @param options - Mutation options

207

* @param state - Optional initial state

208

* @returns Mutation instance

209

*/

210

build<T>(client: QueryClient, options: MutationOptions<T>, state?: MutationState<T>): Mutation<T>;

211

212

/**

213

* Add a mutation to the cache

214

* @param mutation - Mutation instance to add

215

*/

216

add(mutation: Mutation): void;

217

218

/**

219

* Remove a mutation from the cache

220

* @param mutation - Mutation instance to remove

221

*/

222

remove(mutation: Mutation): void;

223

224

/**

225

* Clear all mutations from the cache

226

*/

227

clear(): void;

228

229

/**

230

* Get all mutations in the cache

231

* @returns Array of all Mutation instances

232

*/

233

getAll(): Array<Mutation>;

234

235

/**

236

* Find the first mutation matching the filters

237

* @param filters - Mutation filters to match against

238

* @returns First matching Mutation instance or undefined

239

*/

240

find<T>(filters: MutationFilters): Mutation<T> | undefined;

241

242

/**

243

* Find all mutations matching the filters

244

* @param filters - Mutation filters to match against

245

* @returns Array of matching Mutation instances

246

*/

247

findAll(filters?: MutationFilters): Array<Mutation>;

248

249

/**

250

* Subscribe to cache events

251

* @param callback - Callback function for cache events

252

* @returns Unsubscribe function

253

*/

254

subscribe(callback: (event: MutationCacheNotifyEvent) => void): () => void;

255

256

/**

257

* Notify cache listeners of an event

258

* @param event - Cache event to broadcast

259

*/

260

notify(event: MutationCacheNotifyEvent): void;

261

262

/**

263

* Check if a mutation can run (respects scoping)

264

* @param mutation - Mutation to check

265

* @returns true if mutation can run

266

*/

267

canRun(mutation: Mutation): boolean;

268

269

/**

270

* Run the next mutation in the scope queue

271

* @param mutation - Mutation that just completed

272

* @returns Promise that resolves when next mutation runs

273

*/

274

runNext(mutation: Mutation): Promise<unknown>;

275

276

/**

277

* Resume all paused mutations

278

* @returns Promise that resolves when all mutations are resumed

279

*/

280

resumePausedMutations(): Promise<unknown>;

281

}

282

283

interface MutationCacheConfig {

284

/**

285

* Called when any mutation encounters an error

286

* @param error - The error that occurred

287

* @param variables - Variables passed to the mutation

288

* @param context - Context from onMutate

289

* @param mutation - The mutation that failed

290

*/

291

onError?: (error: unknown, variables: unknown, context: unknown, mutation: Mutation) => Promise<unknown> | unknown;

292

293

/**

294

* Called when any mutation succeeds

295

* @param data - The data returned by the mutation

296

* @param variables - Variables passed to the mutation

297

* @param context - Context from onMutate

298

* @param mutation - The mutation that succeeded

299

*/

300

onSuccess?: (data: unknown, variables: unknown, context: unknown, mutation: Mutation) => Promise<unknown> | unknown;

301

302

/**

303

* Called when any mutation settles

304

* @param data - The data returned (undefined if error)

305

* @param error - The error that occurred (null if success)

306

* @param variables - Variables passed to the mutation

307

* @param context - Context from onMutate

308

* @param mutation - The mutation that settled

309

*/

310

onSettled?: (data: unknown | undefined, error: unknown | null, variables: unknown, context: unknown, mutation: Mutation) => Promise<unknown> | unknown;

311

}

312

```

313

314

**Usage Examples:**

315

316

```typescript

317

import { MutationCache, QueryClient } from "@tanstack/query-core";

318

319

// Create cache with global mutation handlers

320

const mutationCache = new MutationCache({

321

onError: (error, variables, context, mutation) => {

322

console.error('Mutation failed:', mutation.options.mutationKey, error);

323

324

// Global error handling

325

if (error.status === 401) {

326

// Redirect to login

327

window.location.href = '/login';

328

}

329

},

330

onSuccess: (data, variables, context, mutation) => {

331

console.log('Mutation succeeded:', mutation.options.mutationKey);

332

333

// Global success tracking

334

analytics.track('mutation_success', {

335

mutationKey: mutation.options.mutationKey,

336

});

337

},

338

});

339

340

const queryClient = new QueryClient({ mutationCache });

341

342

// Subscribe to mutation events

343

const unsubscribe = mutationCache.subscribe((event) => {

344

switch (event.type) {

345

case 'added':

346

console.log('Mutation added:', event.mutation.mutationId);

347

break;

348

case 'removed':

349

console.log('Mutation removed:', event.mutation.mutationId);

350

break;

351

case 'updated':

352

console.log('Mutation updated:', event.mutation.mutationId, event.action);

353

break;

354

}

355

});

356

357

// Find pending mutations

358

const pendingMutations = mutationCache.findAll({

359

status: 'pending'

360

});

361

console.log(`${pendingMutations.length} mutations pending`);

362

363

// Check mutation queue status

364

const allMutations = mutationCache.getAll();

365

const queuedMutations = allMutations.filter(m => !mutationCache.canRun(m));

366

console.log(`${queuedMutations.length} mutations queued`);

367

368

// Resume paused mutations (e.g., after network reconnection)

369

await mutationCache.resumePausedMutations();

370

371

// Cleanup

372

unsubscribe();

373

```

374

375

### Cache Events

376

377

Understanding cache events for advanced cache monitoring and debugging.

378

379

```typescript { .api }

380

type QueryCacheNotifyEvent =

381

| QueryCacheNotifyEventAdded

382

| QueryCacheNotifyEventRemoved

383

| QueryCacheNotifyEventUpdated

384

| QueryCacheNotifyEventObserverAdded

385

| QueryCacheNotifyEventObserverRemoved

386

| QueryCacheNotifyEventObserverOptionsUpdated

387

| QueryCacheNotifyEventObserverResultsUpdated;

388

389

interface QueryCacheNotifyEventAdded {

390

type: 'added';

391

query: Query;

392

}

393

394

interface QueryCacheNotifyEventRemoved {

395

type: 'removed';

396

query: Query;

397

}

398

399

interface QueryCacheNotifyEventUpdated {

400

type: 'updated';

401

query: Query;

402

action: Action;

403

}

404

405

interface QueryCacheNotifyEventObserverAdded {

406

type: 'observerAdded';

407

query: Query;

408

observer: QueryObserver;

409

}

410

411

interface QueryCacheNotifyEventObserverRemoved {

412

type: 'observerRemoved';

413

query: Query;

414

observer: QueryObserver;

415

}

416

417

type MutationCacheNotifyEvent =

418

| MutationCacheNotifyEventAdded

419

| MutationCacheNotifyEventRemoved

420

| MutationCacheNotifyEventUpdated;

421

422

interface MutationCacheNotifyEventAdded {

423

type: 'added';

424

mutation: Mutation;

425

}

426

427

interface MutationCacheNotifyEventRemoved {

428

type: 'removed';

429

mutation: Mutation;

430

}

431

432

interface MutationCacheNotifyEventUpdated {

433

type: 'updated';

434

mutation: Mutation;

435

action: Action;

436

}

437

```

438

439

**Usage Examples:**

440

441

```typescript

442

// Advanced cache monitoring

443

const queryCache = new QueryCache();

444

445

queryCache.subscribe((event) => {

446

// Track query lifecycle

447

if (event.type === 'added') {

448

console.log(`New query created: ${JSON.stringify(event.query.queryKey)}`);

449

450

// Track memory usage

451

const totalQueries = queryCache.getAll().length;

452

console.log(`Total queries in cache: ${totalQueries}`);

453

}

454

455

if (event.type === 'updated') {

456

const { query, action } = event;

457

458

// Monitor specific query state changes

459

if (action.type === 'success') {

460

console.log(`Query succeeded: ${JSON.stringify(query.queryKey)}`);

461

console.log(`Data size: ${JSON.stringify(query.state.data).length} bytes`);

462

}

463

464

if (action.type === 'error') {

465

console.error(`Query failed: ${JSON.stringify(query.queryKey)}`, action.error);

466

}

467

}

468

469

if (event.type === 'observerAdded') {

470

console.log(`Observer added to: ${JSON.stringify(event.query.queryKey)}`);

471

console.log(`Total observers: ${event.query.observers.length}`);

472

}

473

});

474

```

475

476

### Cache Filters

477

478

Advanced filtering options for finding specific queries and mutations.

479

480

```typescript { .api }

481

interface QueryFilters {

482

/** Query key to match (exact or partial based on 'exact' flag) */

483

queryKey?: QueryKey;

484

485

/** Whether to match query key exactly */

486

exact?: boolean;

487

488

/** Filter by stale status */

489

stale?: boolean;

490

491

/** Filter by active status (has observers) */

492

active?: boolean;

493

494

/** Filter by inactive status (no observers) */

495

inactive?: boolean;

496

497

/** Filter by fetch status */

498

fetchStatus?: FetchStatus;

499

500

/** Filter by query status */

501

status?: QueryStatus;

502

503

/** Custom predicate function */

504

predicate?: (query: Query) => boolean;

505

506

/** Filter by query type */

507

type?: QueryTypeFilter;

508

}

509

510

interface MutationFilters {

511

/** Mutation key to match (exact or partial based on 'exact' flag) */

512

mutationKey?: MutationKey;

513

514

/** Whether to match mutation key exactly */

515

exact?: boolean;

516

517

/** Filter by mutation status */

518

status?: MutationStatus;

519

520

/** Custom predicate function */

521

predicate?: (mutation: Mutation) => boolean;

522

}

523

524

type QueryTypeFilter = 'all' | 'active' | 'inactive';

525

type FetchStatus = 'fetching' | 'paused' | 'idle';

526

type QueryStatus = 'pending' | 'error' | 'success';

527

type MutationStatus = 'idle' | 'pending' | 'success' | 'error';

528

```

529

530

**Usage Examples:**

531

532

```typescript

533

// Complex filtering examples

534

const queryCache = new QueryCache();

535

536

// Find all stale user queries

537

const staleUserQueries = queryCache.findAll({

538

queryKey: ['user'],

539

exact: false,

540

stale: true,

541

});

542

543

// Find queries that are currently fetching

544

const fetchingQueries = queryCache.findAll({

545

fetchStatus: 'fetching',

546

});

547

548

// Find inactive queries older than 1 hour

549

const oldInactiveQueries = queryCache.findAll({

550

inactive: true,

551

predicate: (query) => {

552

const oneHourAgo = Date.now() - 60 * 60 * 1000;

553

return query.state.dataUpdatedAt < oneHourAgo;

554

},

555

});

556

557

// Custom cleanup based on filters

558

const cleanupOldQueries = () => {

559

const queriesToRemove = queryCache.findAll({

560

predicate: (query) => {

561

// Remove queries older than 24 hours with no observers

562

const oneDayAgo = Date.now() - 24 * 60 * 60 * 1000;

563

return query.observers.length === 0 &&

564

query.state.dataUpdatedAt < oneDayAgo;

565

},

566

});

567

568

queriesToRemove.forEach(query => {

569

queryCache.remove(query);

570

});

571

572

console.log(`Cleaned up ${queriesToRemove.length} old queries`);

573

};

574

575

// Run cleanup periodically

576

setInterval(cleanupOldQueries, 60 * 60 * 1000); // Every hour

577

```

578

579

## Core Types

580

581

```typescript { .api }

582

interface QueryOptions<T> {

583

queryKey: QueryKey;

584

queryFn?: QueryFunction<T>;

585

enabled?: boolean;

586

networkMode?: NetworkMode;

587

retry?: RetryValue<T>;

588

retryDelay?: RetryDelayValue<T>;

589

staleTime?: number;

590

gcTime?: number;

591

meta?: QueryMeta;

592

initialData?: T;

593

initialDataUpdatedAt?: number;

594

structuralSharing?: boolean;

595

}

596

597

interface MutationOptions<T> {

598

mutationKey?: MutationKey;

599

mutationFn?: MutationFunction<T>;

600

retry?: RetryValue<T>;

601

retryDelay?: RetryDelayValue<T>;

602

networkMode?: NetworkMode;

603

meta?: MutationMeta;

604

scope?: { id: string };

605

}

606

607

type QueryKey = ReadonlyArray<unknown>;

608

type MutationKey = ReadonlyArray<unknown>;

609

type NetworkMode = 'online' | 'always' | 'offlineFirst';

610

```